Совершено независимо от того как вы относитесь к PHP 7, он будет выпущен в этом году. Рабочее предложение по PHP 7 прошло практически единогласно (32 к 2). Теперь набор функций уже зафиксирован и мы увидим первый релиз уже в середине июня.
Но что это значит для конечного пользователя? Все мы видели с каким нежеланием веб хостинги переходили на PHP 5.х. Сколько мы увидим новых проблем связанных с обратной совместимостью и насколько это замедлит переход на последнюю версию?
На этот вопрос однозначного ответа нет. Читайте дальше.
Было решено несколько серьезных проблем языка. В дополнению к этому основной целью релиза стали повышение производительности и решение проблем совместимости. Углубимся в детали.
Решение проблем совместимости
Самым важным (и более незаметным) дополнением стало введение абстрактного синтаксического дерева (AST) — промежуточное представление кода в процессе компиляции (разделение парсера и компилятора). Имея такой инструмент мы сможем не только костыли с проблемных участков, но и создавать более производительный opcode.
Второй важный пункт — введение универсального синтаксиса для переменных. Именно он и может добавить разработчикам головной боли. Это дополнение решает многочисленные несоответствия, связанных с вычислением значений переменных. Например, получить значение свойства можно как при помощи ($object->closureProperty)()
, так и путем цепочки статичных вызовов:
<?php
class foo { static $bar = 'baz'; }
class baz { static $bat = 'Hello World'; }
baz::$bat = function () { echo "Hello World"; };
$foo = 'foo';
($foo::$bar::$bat)();
Так же изменения коснулись семантики. В частности переменных-переменных/свойств.
До PHP 7, $obj->$properties['name']
давало доступ к свойству чьё имя содержится в ключах массива $properties
. При работе с универсальным синтаксисом переменных ключ name
даст вам доступ к свойству чьё имя содержится в $properties
.
Рассмотрим на примере:
<?php
$obj->$properties['name']
В PHP 5.6 эта строка была бы обработана следующим образом:
<?php
$obj->{$properties['name']}
а в PHP 7:
<?php
{$obj->$properties}['name']
Конечно применение переменных-переменных встречается довольно редко, что не скажешь об обращении к свойствам объекта. Конечно, вы можете легко избавится от этой проблемы при помощи фигурных скобок, как показано в примере выше, таким образом получив одинаковое поведение в PHP обоих версий.
Производительность
Одна из основных причин перехода на PHP 7 — это значительное повышение производительности за счет применения phpng. Такой прирост производительности должен помочь небольшим хостингам, так как они смогут принять на себя большее число клиентов не внося никаких изменений в оборудование.
На данный момент, в зависимости от того чей тест производительности вы увидите, производительность PHP 7 стала соизмерима с Facebook HHVM, который использует JIT-компиляцию. Именно она компилирует команды PHP до уровня машинных команд (при возможности).
Не смотря на то, что JIT-компилятор очень много обсуждался, он не был включен в PHP 7. Конечно, нельзя сказать наверняка насколько повысилась бы производительность, если бы было принято иное решение, но было бы довольно интересно взглянуть на результаты, если вдруг кто-то решит создать подобный компилятор!
В дополнение к производительности, в PHP 7 улучшен процесс работы с памятью путем оптимизации структуры внутренних данных. А такая оптимизация, как правило, оказывает немалое влияние на производительность.
Проблемы обратной совместимости
Хотя разработчики определенно старались сохранить обратную совместимость, но, как правило, существуют моменты в которых это просто невозможно.
Но, хотелось бы отметить, что почти все эти проблемы малозначительны, как например ошибки при обращении к методу не объекта, за исключением проблем в универсальным синтаксисом переменных:
<?php
set_error_handler(function($code, $message) {
var_dump($code, $message);
});
$var = null;
$var->method();
echo $e->getMessage(); // Fatal Error: Call to a member function method() on null
echo "Hello World"; // Still runs
Были удалены ASP и script теги, то есть вы больше не сможете использовать теги <%
, <%=
и <script language=”php”>
и, соответственно, их закрывающие теги.
Другой важный момент — удаление всего функционала, отмеченного как deprecated. Были удалены регулярные выражения совместимые с POSIX (ext/reg PHP 5.3) и старое расширение ext/mysql
(deprecated c PHP 5.5).
Очередная проблема обратной совместимости проявилась в возможности использования нескольких default
выражений в switch. До PHP 7 было допустимо:
<?php
switch ($expr) {
default:
echo "Hello World";
break;
default:
echo "Goodbye Moon!";
break;
}
Раньше обрабатывался только последний default. А в PHP 7 вы получите ошибку:
Fatal error: Switch statements may only contain one default clause
Новые возможности
Довольно нехотя нам приходится разбираться с проблемами обратной совместимости. Мы увидели прирост в производительности. Но, мы также получаем новый функционал. Именно все новое и доставляет удовольствие в работе с новыми программными продуктами и PHP 7 не исключение.
Тайпхинтинг по скалярным величинам и возвращаемое значение
Начнем с самого противоречивого нововведения в PHP 7 — тайпхинтинг для скалярных типов. Внедрение этого функционала было принято на грани отказа в голосовании. В последствии автор RFC покинул проект. За чем последовали несколько новых RFC и соревнующихся между собой решений по ним. Но в итоге прошел оригинальный RFC.
Для конечных пользователей это означает, что вы сможете использовать тайпхинтинг при работе со скалярными величинами. А именно: int
, float
, string
и bool
. По-умолчанию тайпхинтинг не строгий, то есть допускается применение значения другого типа. Что означает, что при передачи int(1)
в функцию, которая ожидает увидеть float
, то такой вызов будет сконвертирован в float(1.0)
. Вызвав float(1.5)
в функцию, требующую int
, вы получите int(1).
Приведем пример:
<?php
function sendHttpStatus(int $statusCode, string $message) {
header('HTTP/1.0 ' .$statusCode. ' ' .$message);
}
sendHttpStatus(404, "File Not Found"); // integer and string passed
sendHttpStatus("403", "OK"); // string "403" coerced to int(403)
В дополнение к этому вы можете установить строгий вариант тайпхинтинга, указав declare(strict_types=1)
в начале файла. Таким образом все функции, которые будут вызваны в этом файле будут полностью соблюдены своему объявлению. Хочу отметить, что это распространяется только на определенный файл, а не на тот, в котором описана переменная.
Если функции будет передан несоответствующий параметр, то будет вызвана ошибка:
<?php
declare(strict_types=1); // must be the first line
sendHttpStatus(404, "File Not Found"); // integer and string passed
sendHttpStatus("403", "OK");
// Catchable fatal error: Argument 1 passed to sendHttpStatus() must be of the type integer, string given
Дальше больше. PHP 7 поддерживает тайпхинтинг по возвращаемым типам. Чтобы указать возвращаемый тип, следует применять следующий синтаксис:
<?php
function isValidStatusCode(int $statusCode): bool {
return isset($this->statuses[$statusCode]);
}
В этом примере функция должна вернуть булево значение. На возвращаемые значения накладываются те же правила, что и на тайпхинтинг типов.
Комбинированный оператор сравнения
Мое любимое дополнение в PHP 7 — комбинированный оператор сравнения (<=>). Он является дополнительным к операторам больше и меньше.
Он работает как strcmp()
и version_compare()
, то есть возвращает -1 если левый операнд меньше, чем правый, 0 — если они равны и 1 — если левый операнд больше. Основное отличие заключается в том, что он применим к любым двум операндам.
Этот оператор часто встречается в функциях обратного вызова при работе с сортировкой данных:
<?php
// Pre Spacefaring^W PHP 7
function order_func($a, $b) {
return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
}
// Post PHP 7
function order_func($a, $b) {
return $a <=> $b;
}
Заключение
В этой статье мы рассмотрели только некоторые из наиболее важных решений проблемы совместимости в PHP 7, а так же две новые функции.
В следующей статье мы разберем еще шесть нововведений в PHP 7, о которых определенно стоит знать. И завершим мы тем, как вы можете помочь разработке PHP 7.
P.S. а пока эта статья находится в работе, поделитесь своим мнением касательно PHP 7. Расскажите, что вы ждете больше всего, а что вас разочаровало.