Что нового в PHP 7?

Прошло уже почти 2 года после того, как состоялся официальный релиз PHP 7 ( 3 декабря 2015 года. Версия получила маркировку PHP 7.0.0 ) а я, как обычно, только начал интересоваться темой. Что поделаешь, такой уж я есть. Все-таки я еще не видел ни одного сервера с рабочим PHP v7, и по работе последнее время использовал только PHP 5.6. Но, наконец, настал тот час, когда настало время задуматься о подготовке плацдарма в виде знаний для перехода на следующую версию. Итак, что же нового или другого будет в PHP 7, чего не было в более ранних версиях:
Группировка оператора use
До PHPv7:
1 2 3 | use Framework\Module\Foo; use Framework\Module\Bar; use Framework\Module\Baz; |
C PHPv7:
1 | use Framework\Module\{Foo, Bar, Baz}; |
Более лаконично и просто можно перечислять объявление используемых пространств имен.
Комбинирование операторов сравнения
Это новый оператор <=>, называется spaceship (космический корабль по-нашему). Он возвращает -1, 0 или 1 если $a, соответственно, меньше, равно или больше чем $b.
До PHPv7:
1 2 3 4 5 | if ($a < $b) echo -1; if ($a = $b) echo 0; if ($a > $b) echo 1; |
C PHPv7:
1 | a <=> b |
Примеры использования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // Целые echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // Рациональные echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // Строки echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 |
Ожидания
Это то, что в оригинальной терминологии именуется как Expectations. Это улучшенная, обратно совместимая версия старой функции assert().
Пример:
1 | void assert (mixed $expression [, string|Exception $message]); |
1 2 3 4 5 | ini_set('assert.exception', 1); class CustomError extends AssertionError {} assert(false, new CustomError('Error in code')); |
Данный пример выдаст сообщение:
1 | Fatal error: Uncaught CustomError: Some error message |
Функция целочисленного деления intdiv()
Новая функция intdiv() производит целочисленное деление операндов и возвращает его результат.
Пример:
1 | var_dump(intdiv(10, 3)); // int(3) |
Оператор ??
?? — это оператор объединения с null, необходимый для достаточно распространенного действия, когда совместно используются тернарный оператор и функция isset(). Он возвращает первый операнд, если он задан и не равен NULL, а в обратном случае возвращает второй операнд.
До PHPv7:
1 | $route = isset($_GET['route']) ? $_GET['route'] : 'index'; |
C PHPv7:
1 | $route = $_GET['route'] ?? 'index'; |
Можно использовать в цепочке, теоретически, бесконечной:
1 | $route = $_GET['route'] ?? CONST_DEFAULT_URL ?? 'index'; |
Декларация скалярных типов
Это то, что в оригинальной терминологии именуется как Scalar types.
Добавлены новые типы, которые могут использоваться для декларации параметров: строки (string), целые (int), рациональные числа (float) и логические значения (bool).
C PHPv7:
1 2 3 4 5 6 | function sumOfInts(int ...$ints) { return array_sum($ints); } var_dump(sumOfInts(2, '3', 4.1)); // int(9) |
Для установки строгого режима, в самом начале файла необходимо поместить одну директиву declare. Это означает, что строгость декларации работает на уровне файла и не затрагивает весь остальной код. Эта директива затрагивает не только декларацию параметров, но и возвращаемые значения функций.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | declare(strict_types=1); function multiply(float $x, float $y) { return $x * $y; } function add(int $x, int $y) { return $x + $y; } var_dump(multiply(2, 3.5)); // float(7) var_dump(add('2', 3)); // Fatal error: Uncaught TypeError: Argument 1 passed to add() //must be of the type integer, string given... |
Возврат значений
Это то, что в оригинальной терминологии именуется как Return Types. Аналогично как и декларация скалярных типов, декларация типа возвращаемого значения указывает, значение какого типа должна вернуть функция.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function arraysSum(array ...$arrays): array { return array_map(function(array $array): int { return array_sum($array); }, $arrays); } print_r(arraysSum([1,2,3], [4,5,6], [7,8,9])); Array ( [0] => 6 [1] => 15 [2] => 24 ) |
При использовании наследования в классах дочерние методы методов должны соответствовать типам объявлений, указанным в родительском классе / интерфейсе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class A {} class B extends A {} class C { public function test() : A { return new A; } } class D extends C { // overriding method C::test() : A public function test() : B // Fatal error due to variance mismatch { return new B; } } |
Return:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class A {} interface SomeInterface { public function test() : A; } class B implements SomeInterface { public function test() : A // Окей { return null; // Fatal error: Uncaught TypeError: Return value of B::test() must be an instance of A, null returned... } } |
Анонимные классы
Добавлена поддержка анонимных классов с помощью new class. Их можно использовать тогда, когда нужен одноразовый класс и создавать полноценный класс, а потом его объект не имеет смысла:
До PHPv7:
1 2 3 4 5 6 7 8 | class Logger { public function log($msg) { echo $msg; } } $util->setLogger(new Logger()); |
C PHPv7:
1 2 3 4 5 6 | $util->setLogger(new class { public function log($msg) { echo $msg; } }); |
Метод Call
Является более производительным и коротким способом временного связывания области действия объекта с замыканием и его вызовом.
До PHPv7:
1 2 3 4 5 | $getXCB = function() {return $this->x;}; $getX = $getXCB->bindTo(new A, 'A'); // биндим А к лямбде echo $getX(); // 1 |
C PHPv7:
1 2 3 | $getX = function() {return $this->x;}; echo $getX->call(new A); // 1 |
Пока что это весь список, что может пригодиться. Если хотите что-то добавить, пишите в комментариях. За помощь в составлении материала большое спасибо Stanislav Vitvickiy.
Понятно, что нововведений в PHP 7 уже гораздо больше. Я здесь описал те нюансы, на которые обратил внимание в первую очередь.