Эта статья была рецензирована Томасом Пунтом . Спасибо всем рецензентам 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 вообще, пожалуйста, опубликуйте их ниже!