Команда разработчиков PHP рада сообщить о релизе PHP 7.0.
Несмотря на тот факт, что этот релиз является мажорным, усилия были направлены на то, чтобы сделать миграцию настолько безболезненной, насколько это возможно. Удаление устаревшей функциональности и устранение несоответствий в языке — основные направления для этой версии.
Abstract Syntax Tree
Наиболее крупным изменением является введение абстрактного синтаксического дерева (AST). Разделение парсера и компилятора позволило избавиться от ряда хаков и сделало реализацию более сопровождаемой и понятной. Кроме того, это позволило реализовать синтаксис, который ранее не был возможным при однопроходном процессе компиляции.
PHPNG
Произведён рефакторинг ядра, который существенно повышает производительность и улучшает использование памяти, а самое главное, дает фундамент для крупных улучшений в будущем, включая JIT. Подробности.
Scalar Type Hints
Добавлены четыре новые декларации для скалярных типов: int, float, string и bool. По умолчанию используется нестрогий режим проверки и данные будут приводиться к тому типу, что указан в декларации:
function add(int $a, int $b) {
// is_int($a) - true
// is_int($b) - true
return $a + $b;
}
add("1", "2");
С помощью новой директивы declare(strict_types=1);
можно включить режим строгой проверки.
Режим распространяется на тот файл, где вызван declare, а не тот, где была определена вызываемая функция.
Если типы не совпадут, это приведет к ошибке:
declare(strict_types=1);
function add(int $a, int $b) {
return $a + $b;
}
add(1.5, 2.5);
// Catchable fatal error: Argument 1 passed to add() must be of the type integer, float given
В дополнение к пользовательским функциями, cтрогий режим проверки типа также влияет на функции стандартной библиотеки и расширений:
declare(strict_types=1);
$foo = substr(52, 1);
// Catchable fatal error: substr() expects parameter 1 to be string, integer given
Return Type Declarations
Добавлена возможность объявить тип возвращаемого значения для функций, генераторов и методов.
Краткий пример синтаксиса в действии:
function foo(): array {
return [];
}
Здесь так же, как и для type-hint, можно объявить строгий режим. Дополнительные примеры можно найти в RFC.
Uniform Variable Syntax
Введён единый синтаксис переменных. Благодаря этому изменению следующие выражения стали корректными:
// support missing combinations of operations
$foo()['bar']()
[$obj1, $obj2][0]->prop
getStr(){0}
// support nested ::
$foo['bar']::$baz
$foo::$bar::$baz
$foo->bar()::baz()
// support nested ()
foo()()
$foo->bar()()
Foo::bar()()
$foo()()
// support operations on arbitrary (...) expressions
(...)['foo']
(...)->foo
(...)->foo()
(...)::$foo
(...)::foo()
(...)()
// two more practical examples for the last point
(function() { ... })()
($obj->closure)()
// support all operations on dereferencable scalars (not very useful)
"string"->toLower()
[$obj, 'method']()
'Foo'::$bar
Но не обошлось и без потери обратной совместимости:
// old meaning // new meaning
$$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz']
$foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz']
$foo->$bar['baz']() $foo->{$bar['baz']}() ($foo->$bar)['baz']()
Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']()
Generator Return Expressions
Добавлена возможность возвращать значения из генераторов.
function gen() {
yield "Hello";
yield " ";
yield "Sun!";
return "Goodbye Moon!";
}
$gen = gen();
foreach ($gen as $value) {
echo $value;
}
// Hello Sun!
echo $gen->getReturn(); // Goodbye Moon!
Generator Delegation
Введён новый синтаксис yield from <expr>
, позволяющий генераторам делегировать операции Traversable объектам и массивам.
function hello() {
yield "Hello";
yield " ";
yield "Sun!";
yield " ";
yield from goodbye();
}
function goodbye() {
yield "Goodbye";
yield " ";
yield "Moon!";
}
$gen = hello();
foreach ($gen as $value) {
echo $value;
}
// Hello Sun! Goodbye Moon!
Anonymous classes
Добавлена поддержка анонимных классов.
Они могут быть использованы вместо полного определения класса для одноразовых объектов:
(new class extends ConsoleProgram {
public function main() {
/* ... */
}
})->bootstrap();
Closure::call
PHP7 добавляет легкий способ переопределить $this для анонимной функции прямо во время вызова с помощью Closure::call().
class A {
private $x = 1;
}
// Pre PHP 7 code
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // intermediate closure
echo $getX();
// PHP 7+ code
$getX = function() {return $this->x;};
echo $getX->call(new A);
Throwable Interface
Изменена иерархия исключений. А именно, введён интерфейс Throwable, который реализуют два базовых исключения: Exception и Error. Пользовательские классы не могут реализовывать этот интерфейс.
Таким образом, новая иерархия выглядит вот так:
-
interface Throwable
-
Exception implements Throwable
- ...
- Error implements Throwable
- TypeError extends Error
- ParseError extends Error
- AssertionError extends Error
-
Exception implements Throwable
Unicode Codepoint Escape Syntax
Добавлен новый экранирующий символ \u, который позволяет указывать специфические unicode-символы внутри PHP-строк:
echo "\u{aa}"; // ª
echo "\u{0000aa}"; // ª (same as before but with optional leading 0's)
echo "\u{9999}"; // 香
Combined Comparison (Spaceship) Operator
Добавлен новый оператор комбинированного сравнения: (expr) <=> (expr)
.
Он возвращает 0, если оба операнда равны, 1 в случае, когда левый операнд больше правого и -1, если правый больше левого.
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
Group Use Declarations
Добавлена возможность группировки use деклараций.
// Before:
use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\Common\Collections\Expr\Value;
use Doctrine\Common\Collections\Expr\CompositeExpression;
// After:
use Doctrine\Common\Collections\Expr\{ Comparison, Value, CompositeExpression };
Null coalesce operator
Ещё один новый оператор — ??, который возвращает левый операнд, если тот не имеет значение NULL, в противном случае возвращается правый операнд. В отличии от короткого тернарного оператора ?:, он работает как isset().
// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// Coalesces can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
Прочие изменения
Особо стоит отметить, что из PHP была удалена вся функциональность помеченная устаревшей в версиях 5.x.x, включая расширения ereg и mysql.
Следующие возможности объявлены устаревшими и будут удалены в будущих версиях:
- Конструкторы классов в стиле PHP 4.
- Статические вызовы нестатических методов.
- Опция salt для password_hash().
- Опция capture_session_meta для SSL context.
>>> Руководство по миграции с PHP 5.6.x
>>> Список изменений