Нововведения в PHP 7.3


Ожидается, что PHP 7.3 выйдет осенью 2018 года. Однако, подготовительная работа над новой версией языка идет уже сейчас. Все обсуждения командой разработчиков ядра PHP ведутся на открытых площадках, поэтому, информация о предполагаемых нововведениях в PHP 7.3 доступна любому желающему. Так вот, на данный момент в нововведениях PHP 7.3 значатся:

  • Более гибкий синтаксис записи heredoc и nowdoc строк;
  • Получение возможности использования запятой, как завершающего символа в вызовах методов и функций;
  • Исключения при выполнении json_encode() и json_decode();
  • Использование ссылочных переменных в функции list();
  • Введение функции is_countable().

Пройдемся по списку выше более подробно.

Более гибкий синтаксис записи heredoc и nowdoc строк

Данный способ объявления особенно удобен, когда приходится работать со строками, расположенными на нескольких строчках. Сейчас данный синтаксис имеет особо строгие требования к окончанию объявления строк таким способом. Рассмотрим строку:

$foo = <<<IDENTIFIER
the crazy dog jumps over the lazy fox
"foo" bar;
IDENTIFIER

В ней последний идентификатор IDENTIFIER должен быть первой последовательностью символов на новой строке, также после этого идентификатора не должно располагаться каких-либо других символов, за исключением пробелов и табуляции.

С выходом PHP 7.3 требования к использованию синтаксиса heredoc и nowdoc несколько смягчатся. А именно:

  • Завершающий объявление строки идентификатор не обязательно должен являться первой последовательность символов на новой строке;
  • Завершающему объявлению строки идентификатору могут предшествовать символы пробела, либо табуляции( но не пробелы и табуляция совместно);
  • Все пробелы и табуляция, предшествующие завершающему объявлению строки будут вырезаны из объявляемой строки;
  • После завершающего идентификатора на текущей строке могут использоваться другие выражения языка.

Таким образом, следующий код не вызовет никаких ошибок:

$foo = ['foo', 'bar', <<<EOT
  baz
    -  hello world! --
  ahoy
  EOT, 'qux', 'quux'
];
var_dump($foo);

Выведется:

array(5) {         
  [0]=>            
  string(3) "foo"  
  [1]=>            
  string(3) "bar"  
  [2]=>            
  string(29) "baz  
  -  hello world! --
ahoy"
  [3]=>
  string(3) "qux"
  [4]=>
  string(4) "quux"
}
RFC

Получение возможности использования запятой, как завершающего символа в вызовах методов и функций

Данное нововведения является логическим продолжением уже используемой возможности оставлять необязательные запятые при объявлении массива или используемого пространства имен:

# Currently possible
use Foo\Bar\{
    Foo,
    Bar,
};
 
$foo = [
    'foo',
    'bar',
];

Единственный случай, когда такая мелочь является хоть сколько-нибудь полезной — при отображении изменений в системах контроля версий (например, git) не отображается лишняя строка, как если бы пришлось добавлять оконечную запятую. Таким образом, с PHP 7.3 станет доступным следующий синтаксис:

unset(
    $foo,
    $bar,
    $baz,
);
class Foo
{
  public function __construct(...$args) {
    //
  }
 
  public function bar(...$args) {
    //
  }
 
  public function __invoke(...$args) {
    //
  }
}
 
$foo = new Foo(
  'constructor',
  'bar',
);
 
$foo->bar(
  'method',
  'bar',
);
$foo(
  'invoke',
  'bar',
);

Однако, использование синтаксиса ниже в объявлении функций и методов вызовет, как и раньше, ошибку:

# Parse error
function bar($a, $b,) {
    //
}

Лично я скептически отношусь к данному нововведению и если и буду его использовать, то крайне редко.

RFC

Исключения при выполнении json_encode и json_decode

Предлагается ввести новую опцию JSON_THROW_ON_ERROR, которую можно передавать в функции json_encode() и json_decode() с целью их изменения поведения. На данный момент, включая PHP 7.2 если при выполнении указанных функций возникнет ошибка, то вернется false в качестве результата. Это является отличным местом для багов, поскольку не каждый разработчик анализирует ответ на наличие false, надеясь получить валидный результат. С выходом же PHP 7.3 код, обрабатывающий json, может заключаться в стандартные блоки try-catch для отлова исключений \JsonException:

try {
  json_decode("{", false, 512, JSON_THROW_ON_ERROR);
}
catch (\JsonException $exception) {
  echo $exception->getMessage(); // echoes "Syntax error"
}

Как по мне, данное нововведение снимет одно из самых неприятных поведений PHP, которое даже было описано в нашумевшей статье PHP: фрактал плохого дизайна. В общем, категорически приветствую данное нововведение.

RFC

Использование ссылочных переменных в функции list()

Функция list() используется для быстрого присваивания переменным значений массива. До настоящего момента, включая PHP 7.2, нет возможности присваивать переменным значения массива по ссылке. В текущих версиях PHP следующий код будет приводить к Fatal Error:

$arr = ['apple', 'orange'];
list($a, &$b) = $arr;
$b = 'banana';
echo $arr[1];
// Fatal error: [] and list() assignments cannot be by reference in .. on line ..

Напротив, с использованием PHP 7.3 такой код сработает, и из переменной $arr[1] на экран выведется ‘banana’.

RFC

Введение функции is_countable()

В PHP 7.2 объявлено устаревшими много функций, а также вариантов использования кода. Так, при передаче функции count() переменной, не являющейся countable, PHP показывал предупреждение. Чтобы исключить показ данного предупреждения, необходимо, чтобы переменная, передаваемая в функцию count(), либо являлась массивом, либо реализовывала интерфейс \Countable:

if (is_array($foo) || $foo instanceof Countable) {
    // $foo is countable
}

Чтобы постоянно не копипастить эти два условия, предлагается ввести функцию is_countable(), которая сочетает эти условия в себе. Код выше в PHP 7.3 может выглядеть так:

if (is_countable($foo)) {
    // $foo is countable
}
RFC
0   0   0000-00-00 00:00:00