Статьи

Что нового и интересного в PHP 7.1?

Эта статья была рецензирована Томасом Пунтом . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!


Сообщество PHP стало популярным благодаря последнему объявлению PHP 7 и всем полезным для языка. Релиз PHP 7.1 предлагает больше хороших новостей и возможностей. В этой статье рассматриваются наиболее важные из них, и вы должны проверить PHP RFC для полного списка.

Летающий слон

ArgumentCountError Exception

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

// PHP 5.6 function sum($a, $b) { return $a + $b; } sum(); // Warning: Missing argument 1 for sum() // Warning: Missing argument 2 for sum() sum(3); // Warning: Missing argument 2 for sum() sum(3, 4); 

Предупреждения в этом случае бесполезны, и разработчик должен проверить, все ли аргументы установлены правильно. В PHP 7.1 эти предупреждения были преобразованы в исключение ArgumentCountError .

 // PHP 7.1 function sum($a, $b) { return $a + $b; } sum(); // Fatal error: Uncaught ArgumentCountError: Too few arguments to function sum(), 0 passed in /vagrant/index.php on line 18 and exactly 2 expected in /vagrant/index.php:13 sum(3); // skipped sum(3, 4); // skipped 

Обнуляемые типы

В PHP 7 добавлены объявления типов для параметров и возвращаемых типов, но казалось, что чего-то не хватает! Обнуляемые типы позволяют указанному типу принимать либо этот тип, либо ноль. Вот пример:

 function sum(int $a, int $b): ?int { return $a + $b; } 

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

 function sum(?int $a, ?int $b): ?int { if ($a == null || $b == null) { return null; } return $a + $b; } 

Неожиданно то, что вызов функции без аргументов вызовет исключение!

 var_dump(sum(null, null)); // NULL var_dump(sum()); // throw ArgumentCountError exception 

Это означает, что вы должны явно указывать аргументы, когда они не имеют значения по умолчанию.

Также следует иметь в виду, что при переопределении или реализации методов вы не можете добавить обнуляемый тип к возвращаемому типу, но вы можете удалить его. И обратное верно для аргументов, вы не можете удалить тип Nullable из аргументов, но вы можете добавить его!

 interface Fooable { function foo(): ?Fooable; } interface StrictFooable extends Fooable { function foo(): Fooable; // valid } interface Fooable { function foo(): Fooable; } interface LooseFooable extends Fooable { function foo(): ?Fooable; // invalid } 

Разрушающие массивы

Мы привыкли делать следующее при разрушении массивов.

 list($a, $b, $c) = [1, 2, 3]; var_dump($a, $b, $c); // int(1) int(2) int(3) 

Но попытка этого не удалась, потому что мы не могли указать ключи для извлечения, и функция пыталась использовать индексные ключи.

 list($a, $b, $c) = ["a" => 1, "b" => 2, "c" => 3]; var_dump($a, $b, $c); // NULL NULL NULL 

Этот RFC обеспечивает больший контроль над деструктуризацией массива. Код выше может быть изменен на это.

 list("a" => $a, "b" => $b, "c" => $c) = ["a" => 1, "b" => 2, "c" => 3]; var_dump($a, $b, $c); // int(1) int(2) int(3) 

Функция list теперь принимает ключи для деструктуризации массива, и поскольку это часто используется, был введен новый компактный синтаксис. Возьми это как пример.

 ["a" => $a, "b" => $b, "c" => $c] = ["a" => 1, "b" => 2, "c" => 3]; var_dump($a, $b, $c); // int(1) int(2) int(3) 

Круто, не правда ли? И это также работает на многомерных массивах.

 [[$a, $b], [$c, $d]] = [[1, 2], [3, 4]]; var_dump($a, $b, $c, $d); // int(1) int(2) int(3) int(4) [["b" => $b], ["c" => $c]] = [["a" => 1, "b" => 2], ["c" => 3, "d" => 4]]; var_dump($b, $c); // int(2) int(3) 

Итерируемый тип

iterable псевдотип добавляется для соединения типа примитива массива и интерфейса Traversable который используется, чтобы сделать значение итеративным. Возьмите приведенный ниже код в качестве примера.

 // PHP 5.6 function dump(array $items) { var_dump($items); } dump([2, 3, 4]); dump(new Collection()); 
 array(3) { [0]=> int(2) [1]=> int(3) [2]=> int(4) } Catchable fatal error: Argument 1 passed to dump() must be of the type array, object given... 

Но в этом случае функция не примет повторяемое значение и выдаст ошибку. Это новое изменение позволяет вам использовать iterable описание итеративного значения, вместо того, чтобы устанавливать его вручную.

 // PHP 7.1 function dump(iterable $items) { var_dump($items); } dump([2, 3, 4]); dump(new Collection()); 
 array(3) { [0]=> int(2) [1]=> int(3) [2]=> int(4) } object(Collection)#2 (0) { } 

Закрытие от вызываемой функции

Новый метод fromCallable обеспечивает эффективный и компактный способ создания объектов Closure из вызываемых. Вот пример:

 $callback = Closure::fromCallable([$this, 'fn']); 

Пустой тип возврата

Это одна из моих любимых новых функций. Он завершает функцию возвращаемых типов, представленную в PHP 7, где функции могут ничего не возвращать и, следовательно, будут вынуждены возвращать ноль!

 function dump($object): void { var_dump($object); } 

Функция void может опустить оператор return или добавить пустой ( return; ).

Класс Постоянная видимость

Это небольшое изменение, но существенная часть в ООП, которая обеспечивает инкапсуляцию. Это добавляет модификаторы видимости к константам класса.

 class Post { protected const PUBLISHED = 1; protected const DRAFT = 2; protected const TRASHED = 3; // ... } 

Отлов нескольких типов исключений

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

 // ... try { $user->payMonth($month); } catch (UserSuspendedException $ex) { DB::rollBack(); return redirect() ->back() ->withInput() ->withErrors([$ex->getMessage()]); } catch (PaidMonthException $e) { DB::rollBack(); return redirect() ->back() ->withInput() ->withErrors([$ex->getMessage()]); } // ... в // ... try { $user->payMonth($month); } catch (UserSuspendedException $ex) { DB::rollBack(); return redirect() ->back() ->withInput() ->withErrors([$ex->getMessage()]); } catch (PaidMonthException $e) { DB::rollBack(); return redirect() ->back() ->withInput() ->withErrors([$ex->getMessage()]); } // ... 

Вы можете удалить дублирование, используя новый синтаксис блока catch:

 // ... try { $user->payMonth($month); } catch (PaidMonthException | UserSuspendedException $ex) { DB::rollBack(); return redirect() ->back() ->withInput() ->withErrors([$ex->getMessage()]); } // ... в // ... try { $user->payMonth($month); } catch (PaidMonthException | UserSuspendedException $ex) { DB::rollBack(); return redirect() ->back() ->withInput() ->withErrors([$ex->getMessage()]); } // ... 

Неверная строковая арифметика

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

 // PHP 5.6 var_dump("1" + "2"); var_dump("1" + "a string"); var_dump("1" + "2 with a string"); 
 int(3) int(1) int(3) 
 // PHP 7.1 var_dump("1" + "2"); var_dump("1" + "a string"); var_dump("1" + "2 with a string"); 
 int(3) Warning: A non-numeric value encountered in /vagrant/index.php on line 17 int(1) Notice: A non well formed numeric value encountered in /vagrant/index.php on line 18 int(3) 

Теперь мы получаем предупреждение, если найдено не числовое значение, и уведомление, если значение не отформатировано ( 2 a string = 2 ).

Вывод

Этот список не охватывает все новые изменения, поэтому обязательно проверьте список RFC для полного списка. Если у вас есть вопрос или комментарий о новых возможностях PHP 7.1 или PHP вообще, пожалуйста, опубликуйте их ниже!