Это первая часть нашей минисерии статей «Чего ждать от PHP7». Читать часть 2
Как многие из вас, вероятно, знают, было принято RFC о согласовании названия следующей основной версии PHP, которая будет называться PHP7. Вы можете почитать об этом в моем PHP5 timeline.
Независимо от ваших чувств по поводу этой темы, PHP7 — это свершившийся факт, и он придет в этом году! RFC с таймлайном выпуска PHP7.0 прошло практически единогласно (32 к 2), сейчас разработчики подошли к стадии заморозки фич, а первый релиз-кандидат (RC) мы увидим уже в середине июня.
Но что все это значит для нас, обычных разработчиков? Сейчас мы видим огромное нежелание веб-хостеров двигаться в направлении новых версий 5.x. Не приведет ли крупное обновление, ломающее обратную совместимость, к еще более медленному движению?
Ответ: посмотрим. Продолжайте читать и узнаете подробности.
Большая часть проблем с некорректным поведением в нестандартных ситуациях была исправлена. Кроме того, производительность и устранение несоответствия — основные направления для этой версии.
Давайте углубимся в детали.
Исправления несоответствий
К сожалению, тикеты про
needle/haystack так и не были решены. Тем не менее, прошли два очень важных RFC. Так что не стоит терять надежды на приход столь необходимой последовательности и ожидаемого синтаксиса.Крупнейшим (и самым незаметным) стало добавление абстрактного синтаксического дерева (Abstract Syntax Tree — AST), являющегося промежуточным представлением кода во время компиляции. С AST core-разработчики смогут лучше обрабатывать пограничные случаи, устранять несоответствия в поведении, а также проложить путь для удивительных вещей в будущем, например, можно будет создавать еще более производительные акселераторы.
Также был введен единый синтаксис переменных, который может причинить много проблем с миграцией на PHP7. Он решает многочисленные несоответствия в вычислении выражений. Например, возможность вызывать анони��ные функции, привязанные к параметрам через
($object->closureProperty)(), а также добавляет возможность вызывать цепочки статических методов:class foo { static $bar = 'baz'; }
class baz { static $bat = 'Hello World'; }
baz::$bat = function () { echo "Hello World"; };
$foo = 'foo';
($foo::$bar::$bat)();
Однако, кое-что все же поменялось. В частности, семантика использования переменных переменных/свойств.
До PHP7,
$obj->$properties['name'] было доступом к свойству, имя которого входило в значение, хранящегося по ключу name массива $properties. Теперь же, доступ будет осуществляться к значению по ключу name массива, который, в свою очередь, определяется значением параметра $properties в объекте.Или, чтобы быть более кратким, если мы принимаем это утверждение:
$obj->$properties['name']
То в PHP5.6, оно будет интерпретировано как:
$obj->{$properties['name']}
А в PHP 7:
{$obj->$properties}['name']
Хотя и использование переменных-переменных, как правило, является пограничным случаем, и весьма неодобряемый сообществом, переменные-параметры — гораздо большая редкость в моей практике. Однако, вы можете легко обойтись без проблем с миграцией, если будете использовать фигурные скобки (как в примерах выше) для обеспечение аналогичного поведения между PHP5.6 и PHP7.
Производительность
Самой большой причиной для перехода на PHP7 является его производительность, которая своими характеристиками в первую очередь обязана phpng. Увеличение производительности может стать реша��щим фактором для быстрого перехода на 7ю версию маленькими хостерами, ведь им удастся разместить больше клиентов на том же оборудовании.
На текущий момент дела обстоят следующим образом: PHP7 находится на одном уровне с HHVM, написанным фейсбуком, который работает в качестве Just In Time (JIT) компилятора, переводящего PHP-код в машинные инструкции.
PHP7 не имеет JIT-компилятора, хотя было много дискуссий о нем. Непонятно какой прирост производительности даст этот шаг, но уверен, будет интересно посмотреть, если кто-то все же решится его сделать!
В дополнение к производительности, приятным побочным эффектом оптимизации внутренней структуры данных будет и значительная экономия памяти.
Изменения, ломающие обратную совместимость
Конечно же, core-разработчики очень старались не сломать обратную совместимость с предыдущими версиями, но, к сожалению, это не всегда возможно сделать при движении языка вперед, обязательно будут те, кто недоволен.
Однако, также как и изменение поведения в связи с вводом Uniform Variable Syntax, большая часть нововведений являются незначительными, например, отлавливаемые фатальные ошибки при вызове метода у не-объекта:
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
Кроме того, APS и теги
script были удалены, вы больше не сможете использовать <% и <%=, или `<script language="php”>` и их закрывающие теги %>, .Другие, гораздо более серьезные изменения, находятся в RFC об удалении ВСЕЙ устаревшей (deprecated) функциональности.
Особо стоит отметить исключение из стандартной поставки расширения posix-совместимых регулярных выражений ext/ereg (не рекомендовано к использованию в 5.3) и старого ext/mysql расширения (заменено на новое в 5.5).
Одним из других минорных изменений является запрет на использование множественного
default в операторе switch. PHP до версии 7 разрешал делать так:switch ($expr) {
default:
echo "Hello World";
break;
default:
echo "Goodbye Moon!";
break;
}
Это приведет к выполнению только последнего. PHP7 же выдаст ошибку:
Fatal error: Switch statements may only contain one default clause
Новые Возможности
Конечно же, мы справимся с последствиями изменений, ломающими обратную совместимость. Мы ценим производительность. Но еще больше мы наслаждаемся новыми возможностями! Новый функционал — вот что делает каждый релиз удовольствием, и PHP7 не исключение.
Скалярный type-hint и возвращаемые значения
Я собираюсь начать с наиболее спорного момента, который был добавлен в PHP7: Scalar Type Hints. RFC на добавлении этой функции почти прошло голосование, но на автора настолько повлияли споры об этом, что он решил покинуть PHP-разработку, а также снял RFC с голосования. За этим последовало еще несколько, с конкурирующими реализациями. Было много общественных волнений, которые в конечном счете закончились (положительно) и оригинальная версия RFC была принята.
Для вас, конечных пользователей, это означает, что вы можете использовать type-hint со скалярными значениями. А именно:
int, float, string и bool. По умолчанию функция работает в нестрогом режиме, а значит они будут просто приводить исходный тип в значение, указанное в подсказке типа. Например, если вы передали в функцию int(1), которая требует нецелочисленное число, то оно будет приводиться к float(1.0). И наоборот: передавая в функцию, требующую целого числа, float(1.5), то будет приходить значение int(1). Пример: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); в верхней части файла и он гарантирует вам, что любой вызов функций, сделанный в этом файле, будет строго придерживаться определенного типа. Это произойдет именно в том файле, где вызван declare, а не в том файле, где была определена вызываемая функция.Если типы не совпадут, это приведет к выбросу отлавливаемой фатальной ошибки:
declare(strict_types=1); // должно быть на первой строчке
sendHttpStatus(404, "File Not Found"); // integer и string переданы
sendHttpStatus("403", "OK");
// Catchable fatal error: Argument 1 passed to sendHttpStatus() must be of the type integer, string given
PHP7 также поддерживает тип возвращаемого значения, который может принимать все те же типы в качестве аргументов. Синтаксис будет как и в hack, двоеточие с аргументом-суффиксом перед скобкой:
function isValidStatusCode(int $statusCode): bool {
return isset($this->statuses[$statusCode]);
}
В данном примере
: bool указывает на то, что функция вернет булево значение.Те же правила, которые применяются к type-hint, работают и здесь в случае объявления строгого режима.
Комбинированный оператор сравнения
Моим любимым дополнением в PHP7 является добавление комбинированного оператора сравнения,
<=>, также известного как Spaceship-оператор. Я могу казаться пристрастным, но он действительно крут, и хорошо сочетается с операторами > и <.Эффективно работает как
strcmp() или же version_compare(), возвращая -1, если левый операнд меньше правого, 0 — если они равны, и 1, если левый больше правого. Основным его отличием от функций является то, что его можно использовать на любых двух операндах, а не только на примитивах.Наиболее распространенное его использование заключается в callback'ах сортировок:
// 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;
}
Далее
Мы проанализировали некоторые из наиболее важных исправлений несоответствий поведения и посмотрели на две новые возможности PHP7.
В следующем посте мы рассмотрим шесть других больших нововведений в PHP7, о которых вы обязательно захотите узнать.
P.S. А пока вы ждете, почему бы не поделиться своими мыслями по поводу того, что будет самым ожидаемым в PHP7? Или может быть есть вещи, которые не хотелось бы видеть в языке?