PHP 7.0.0

December 6, 2015

Третьего декабря 2015 года Команда разработчиков 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 **, позволяющий генераторам делегировать операции 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
    1. Exception implements Throwable
      • ...
    2. Error implements Throwable
      • TypeError extends Error
      • ParseError extends Error
      • AssertionError extends Error

###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.

Полезности и приятности:

  • Добавлена поддержка строк длиной больше 2^31 байт в 64-битных билдах.
  • В качестве значения констант, объявляемых через define() теперь можно указывать массивы.
  • Зарезервированные ключевые слова теперь можно использовать в качестве имен методов.
  • Синтаксис конструкторов в стиле PHP 4 (имя метода конструктора совпадает с именем класса) теперь считается устаревшим.
  • Статичные вызовы (::) нестатичных методов теперь считаются устаревшими.
  • Добавлена константа PHP_INT_MIN.
  • Удалена INI директива «asp_tags». Попытка включить ее приведет к фатальной ошибке. Так же удалена поддержка тэгов в стиле ASP (<%).
  • Удалена INI директива «always_populate_raw_post_data». Переменная $HTTP_RAW_POST_DATA соответственно больше не доступна. Вместо нее используйте дескриптор входного потока php://input.
  • Итерация по массиву при помощи foreach() больше не сдвигает внутренний указатель массива, который можно получать и изменять при помощи функций current()/next()/reset() и им подобных. Так же foreach по значению теперь всегда работает с копией массива.
  • Оператор левого побитового сдвига («) на количество бит, превышающее количество бит в integer теперь всегда возвращает 0. До этого результат зависел от архитектуры процессора. Аналогичный правый сдвиг всегда дает 0 или -1 в зависимости от знака исходного числа (Сдвиг не влияет на старший бит, отвечающий за знак).
  • Строки, содержащие шестнадцатеричные числа теперь всегда обрабатываются как строки и не обрабатываются как числа: is_numeric(«0xFF») теперь false, раньше было true со всеми вытекающими.
  • Целые числа в 64-х битных билдах для Windows теперь представляются в виде 64-х битных, а не как раньше, 32-х, что делало использование х64 сборок на Windows бессмысленным занятием, если нужны манипуляции с большими числами.
  • Удалена поддержка модификатора /e в PCRE. Аналогичная функциональность может быть реализована функцией preg_replace_callback().
  • Удалены старые и не поддерживаемые SAPI и расширения.

###Дополнительные ссылки

Комментарии

comments powered by Disqus