Введение в PHP 7: что нового и что ушло
Опубликовано: 2022-03-11Одним из самых захватывающих событий 2015 года в мире PHP стал выпуск PHP 7, спустя 10 лет после выпуска последней основной версии, PHP 5. Сделав большой шаг вперед, PHP 7 представляет множество новых функций и улучшений производительности. .
Однако он также удаляет старые, устаревшие функции, что приводит к некоторым нарушениям совместимости, что затрудняет переход старых приложений на новую версию. Это руководство должно служить кратким обзором того, чего ожидать, если вы планируете перенести существующие приложения или создать новые поверх PHP 7.
Но подождите, куда делся PHP 6?
Если вы в последнее время не работали с PHP, вам может быть интересно, что случилось с PHP 6, почему перескочили с PHP 5 на PHP 7? Короче говоря, PHP 6 потерпел неудачу. Главной особенностью версии 6 была встроенная поддержка символов Unicode, поскольку PHP используется в основном в веб-разработке, а вебу нужен Unicode, поэтому переход на Unicode в PHP имел смысл.
Идея заключалась в том, чтобы довести полную поддержку Unicode до самого ядра. Это дало бы языку расширенные возможности, от возможности использовать глупые смайлики в качестве имен переменных и функций до мощной функциональности международных строк. Например, когда в другом языке используются прописные и строчные буквы иначе, чем в английском, или когда необходимо преобразовать имя, состоящее из китайских иероглифов, в английское.
К сожалению, этот амбициозный план оказался более серьезной проблемой, чем предполагалось. Большую часть кодовой базы пришлось портировать для поддержки Unicode как для основных, так и для важных расширений, что оказалось утомительным и сложным. Это замедлило разработку других функций языка, разочаровав многих PHP-разработчиков. Появились дополнительные препятствия, которые привели к снижению интереса к разработке собственной поддержки Unicode, что в конечном итоге привело к отказу от проекта.
Поскольку ресурсы, такие как книги и статьи, были написаны для PHP 6 и его поддержки Unicode, новая версия будет переименована в PHP 7, чтобы избежать путаницы.
В любом случае, хватит копаться в печальном прошлом, давайте посмотрим, что принесет PHP 7 на вечеринку.
Битва производительности, PHP 7 против PHP 5
Практически со всеми обновлениями следует ожидать незначительных улучшений производительности. Однако на этот раз PHP предлагает значительное улучшение по сравнению с более ранними версиями, что делает производительность одной из самых привлекательных особенностей PHP 7. Это происходит в рамках проекта «PHPNG», который занимается внутренностями самого Zend Engine.
Благодаря рефакторингу внутренних структур данных и добавлению промежуточного шага к компиляции кода в виде абстрактного синтаксического дерева (AST) достигается более высокая производительность и более эффективное распределение памяти. Сами цифры выглядят очень многообещающе; тесты, проведенные в реальных приложениях, показывают, что PHP 7 в среднем в два раза быстрее, чем PHP 5.6, и потребляет на 50 процентов меньше памяти во время запросов, что делает PHP 7 сильным конкурентом JIT-компилятора Facebook HHVM. Взгляните на эту инфографику от Zend, показывающую производительность некоторых распространенных CMS и фреймворков.
Уменьшение потребления памяти также позволяет меньшим машинам лучше обрабатывать запросы, а также дает возможность создавать микросервисы на основе PHP. Внутренние изменения, в частности реализация AST, также открывают возможности для будущих оптимизаций, которые могут еще больше повысить производительность. В будущих версиях рассматривается новая собственная реализация JIT-компилятора.
Синтаксический сахар PHP 7
PHP 7 поставляется с новыми функциями синтаксиса. Не расширяя возможности самого языка, они обеспечивают лучший или более простой способ сделать ваш код более приятным для написания и приятным для глаз.
Групповые декларации импорта
Теперь мы можем сгруппировать объявления импорта для классов, происходящих из одного и того же пространства имен, в одну строку use
. Это должно помочь осмысленно выровнять объявления или просто сэкономить несколько байтов в ваших файлах.
use Framework\Module\Foo; use Framework\Module\Bar; use Framework\Module\Baz;
С PHP 7 мы можем использовать:
use Framework\Module\{Foo, Bar, Baz};
Или, если вы предпочитаете многострочный стиль:
use Framework\Module{ Foo, Bar, Baz };
Нулевой оператор объединения
Это решает распространенную проблему в программировании на PHP, когда мы хотим присвоить значение переменной из другой переменной, если последняя действительно установлена, или иным образом предоставить ей другое значение. Он обычно используется, когда мы работаем с пользовательским вводом.
До PHP 7:
if (isset($foo)) { $bar = $foo; } else { $bar = 'default'; // we would give $bar the value 'default' if $foo is NULL }
После PHP 7:
$bar = $foo ?? 'default';
Это также может быть связано с рядом переменных:
$bar = $foo ?? $baz ?? 'default';
Оператор космического корабля
Оператор космического корабля <=>
позволяет проводить трехстороннее сравнение двух значений, не только указывая, равны ли они, но и указывая, какое из них больше, при неравенстве, возвращая 1,0 или -1.
Здесь мы можем предпринимать разные действия в зависимости от того, насколько различаются значения:
switch ($bar <=> $foo) { case 0: echo '$bar and $foo are equal'; case -1: echo '$foo is bigger'; case 1: echo '$bar is bigger'; }
Сравниваемые значения могут быть целыми числами, числами с плавающей запятой, строками или даже массивами. Ознакомьтесь с документацией, чтобы получить представление о том, как разные значения сравниваются друг с другом. [https://wiki.php.net/rfc/combined-comparison-operator]
Новые возможности в PHP 7
Но, конечно же, PHP 7 также приносит с собой новые и интересные функции.
Типы скалярных параметров и подсказки по типу возвращаемого значения
PHP 7 расширяет предыдущие объявления типов параметров в методах (классы, интерфейсы и массивы), добавляя четыре скалярных типа; Целые числа ( int
), числа с плавающей запятой ( float
), логические значения ( bool
) и строки ( string
) в качестве возможных типов параметров.
Кроме того, мы можем дополнительно указать, какой тип возвращают методы и функции. Поддерживаемые типы: bool , int , float , string , array , callable , имя класса или интерфейса , self и parent (для методов класса).
class Calculator { // We declare that the parameters provided are of type integer public function addTwoInts(int $x, int $y): int { return $x + $y; // We also explicitly say that this method will return an integer } }
Объявления типов позволяют создавать более надежные приложения и избегать передачи и возврата неправильных значений из функций. К другим преимуществам относятся статические анализаторы кода и IDE, которые обеспечивают лучшее понимание кодовой базы в случае отсутствия DocBlocks.
Поскольку PHP является слабо типизированным языком, определенные значения параметров и типов возвращаемых значений будут преобразованы в зависимости от контекста. Если мы передаем значение «3» в функцию с объявленным параметром типа int
, интерпретатор примет его как целое число и не выдаст никаких ошибок. Если вы этого не хотите, вы можете включить strict mode
, добавив директиву declare
.
declare(strict_types=1);
Это устанавливается для каждого файла, так как глобальная опция разделит репозитории кода на те, которые построены с глобальной строгостью , и те, которые не таковы, что приводит к неожиданному поведению, когда мы объединяем код из обоих.
Исключения двигателя
С добавлением исключений движка фатальные ошибки, которые привели бы к завершению скрипта, могут быть легко обнаружены и обработаны.
Такие ошибки, как вызов несуществующего метода, не приводят к завершению сценария, вместо этого они вызывают исключение, которое может быть обработано блоком try catch, что улучшает обработку ошибок для ваших приложений. Это важно для определенных типов приложений, серверов и демонов, поскольку в противном случае фатальные ошибки потребовали бы их перезапуска. Тесты в PHPUnit также должны стать более удобными, так как фатальные ошибки приводят к падению всего набора тестов. Исключения, а не ошибки, будут обрабатываться для каждого тестового примера.
PHP 7 добавляет ряд новых классов исключений в зависимости от типа ошибок, которые могут возникнуть. Чтобы поддерживать совместимость между версиями, был добавлен новый интерфейс Throwable
, который можно реализовать как из исключений ядра, так и из пользовательских исключений. Это было необходимо, чтобы избежать исключений движка для расширения базового класса исключений, что приводило к более старым исключениям перехвата кода, которых раньше не было.
До PHP 7 это привело бы к завершению скрипта с фатальной ошибкой:
try { thisFunctionDoesNotEvenExist(); } catch (\EngineException $e) { // Clean things up and log error echo $e->getMessage(); }
Анонимные классы
Анонимные классы являются родственниками анонимных функций, которые вы можете использовать в простом краткосрочном экземпляре. Анонимные классы легко создаются и используются так же, как и обычные объекты. Вот пример из документации.
Пред-PHP 7
class MyLogger { public function log($msg) { print_r($msg . "\n"); } } $pusher->setLogger( new MyLogger() );
С анонимным классом:
$pusher->setLogger(new class { public function log($msg) { print_r($msg . "\n"); } });
Анонимные классы полезны при модульном тестировании, особенно при имитации тестовых объектов и сервисов. Это помогает нам избежать тяжелых фиктивных библиотек и фреймворков, создавая простой объект, предоставляющий интерфейс, который мы хотим имитировать.

Функции CSPRNG
Добавлены две новые функции для генерации криптографически защищенных строк и целых чисел.
random_bytes(int $len);
Возвращает случайную строку длины $len
.
random_int(int $min, int $max);
Возвращает число от $min
до $max
.
Синтаксис экранирования кодовой точки Unicode
В отличие от многих других языков, до PHP 7, в PHP не было способа экранировать кодовую точку Unicode в строковых литералах, . Эта функциональность добавляет escape-последовательность \u
для создания таких символов с использованием их кодовой точки UTF-8. Это лучше, чем вставка символов напрямую, поскольку позволяет лучше обрабатывать невидимые символы, а также символы, которые имеют одинаковое графическое представление, но различаются по значению.
echo "\u{1F602}"; // outputs ‚
Обратите внимание, что это нарушает существующий код последовательностью \u
, потому что это меняет поведение.
Генераторы обновляются
Генераторы в PHP также получают некоторые приятные дополнительные функции. Теперь у генераторов есть оператор return, который можно использовать для вывода окончательного значения после итерации. Это может использоваться для проверки того, что генератор был выполнен без ошибок, и позволяет коду, вызвавшему генератор, правильно обрабатывать различные сценарии.
Кроме того, генераторы могут возвращать и выдавать выражения из других генераторов. Это позволяет им разделить сложные операции на более простые и модульные блоки.
function genA() { yield 2; yield 3; yield 4; } function genB() { yield 1; yield from genA(); // 'genA' gets called here and iterated over yield 5; return 'success'; // This is a final result we can check later } foreach (genB() as $val) { echo "\n $val"; // This will output values 1 to 5 in order } $genB()->getReturn(); // This should return 'success' when there are no errors.
Ожидания
Ожидания — это усовершенствование функции assert()
с сохранением обратной совместимости. Они позволяют использовать утверждения с нулевой стоимостью в производственном коде и предоставляют возможность создавать пользовательские исключения в случае сбоя утверждения, что может быть полезно во время разработки.
assert()
становится языковой конструкцией в PHP 7. Утверждения следует использовать в целях отладки только в средах разработки и тестирования. Для настройки его поведения нам предоставлены две новые директивы.
-
zend.assertions
-
1
: генерировать и выполнять код (режим разработки) (значение по умолчанию) -
0
: генерирует код, но обходит его во время выполнения. -
-1
: не генерирует код, что делает его бесплатным (производственный режим)
-
-
assert.exception
-
1
: бросать, когда утверждение терпит неудачу, либо выбрасывая объект, предоставленный в качестве исключения, либо выбрасывая новый объект AssertionError , если исключение не было предоставлено. -
0
: использовать или генерировать Throwable , как описано выше, но генерировать предупреждение только на основе этого объекта, а не генерировать его (совместимо с поведением PHP 5)
-
Подготовка к переходу с PHP 5 на PHP 7
Внедрение основной версии дает возможность изменить/обновить старые функции или даже удалить их, если они считаются слишком старыми или не рекомендуются в течение некоторого времени. Такие изменения могут привести к нарушению совместимости в старых приложениях.
Еще одна проблема, возникающая из-за таких скачков версий, заключается в том, что важные библиотеки и платформы, от которых вы зависите, возможно, еще не обновлены для поддержки последней версии. Команда PHP постаралась сделать новые изменения как можно более обратно совместимыми и сделать миграцию на новую версию максимально безболезненной. Более новым и современным приложениям должно быть легче перейти на новую версию, в то время как более старым приложениям, возможно, придется решить, перевешивают ли преимущества затраты, возможно, решив не обновляться.
Большинство сбоев незначительны и могут быть легко устранены, в то время как другие могут потребовать больше усилий и времени. По сути, если у вас были предупреждения об устаревании в вашем приложении до установки PHP 7, вы, вероятно, получите ошибки, которые сломают приложение до тех пор, пока они не будут исправлены. Вас предупредили, да?
Старые SAPI и расширения
Самое главное, старые и устаревшие SAPI были удалены, как и расширение mysql
(но вы не должны использовать это в первую очередь, верно?). Полный список удаленных расширений и функций можно найти здесь и здесь.
Кроме того, другие SAPI переносятся на PHP 7.
Единый синтаксис переменных
Это обновление внесло некоторые изменения в пользу согласованности для конструкций переменная-переменная. Это позволяет использовать более сложные выражения с переменными, но вносит изменения в поведение в некоторых других случаях, как показано ниже.
// 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']()
Это нарушит поведение приложений, обращающихся к таким значениям. С другой стороны, вы можете сделать несколько изящных вещей, например:
// Nested () foo()(); // Calls the return of foo() $foo->bar()(); // IIFE syntax like JavaScript (function() { // Function body })(); // Nested :: $foo::$bar::$baz
Теги старого стиля удалены
Открывающие/закрывающие теги <% ... %>
, <%= ... %>
, <script language="php"> ... </script>
удалены и больше недействительны. Заменить их на действительные должно быть легко, но что ты вообще с ними делаешь, чудак?
Недопустимые имена для классов, интерфейсов и трейтов
В результате дополнений, таких как типы параметров и возвращаемых типов, классы, интерфейсы и трейты больше не могут иметь следующие имена:
- логический
- инт
- плавать
- нить
- нулевой
- истинный
- ложный
Они вызывают сбои в работе существующих приложений и библиотек, которые их используют, но их должно быть легко исправить. Кроме того, несмотря на то, что они не вызывают ошибок и являются допустимыми, следующие элементы не следует использовать, поскольку они зарезервированы для использования в будущем:
- ресурс
- объект
- смешанный
- числовой
Воздержание от их использования должно избавить вас от работы по их изменению в будущем.
Полный список изменений, которые могут нарушить совместимость, см. в этом документе.
Вы также можете использовать php7cc, который проверяет ваш код и может обнаружить любые потенциальные проблемы, которые могут возникнуть при переходе на PHP 7. Но, конечно, нет лучшего способа, чем установить PHP 7 и убедиться в этом самим.
Возможные проблемы совместимости с PHP 7
Совместимость с инфраструктурой PHP 7
Многие хостинг-сервисы начали добавлять поддержку PHP 7. Это хорошая новость для провайдеров виртуального хостинга, поскольку прирост производительности позволит им увеличить количество клиентских веб-сайтов на своем оборудовании, сократив свои операционные расходы и повысив прибыль. Что касается самих клиентов, то им не следует ожидать слишком большого прироста в этих условиях, но, честно говоря, виртуальный хостинг в любом случае не является выбором, ориентированным на производительность.
С другой стороны, сервисы, предлагающие виртуальные частные серверы или выделенные серверы, получат все преимущества от этого скачка производительности. Некоторые сервисы PaaS, такие как Heroku, раньше поддерживали PHP 7, но другие сервисы, такие как AWS Beanstalk и Oracle OpenShift, отстают. Посетите веб-сайт поставщика PaaS, чтобы узнать, поддерживается ли уже PHP 7 или поддержка появится в ближайшем будущем.
Конечно, поставщики IaaS позволяют вам взять под контроль оборудование и установить PHP 7 (или скомпилировать, если вам это больше нравится). Пакеты PHP 7 уже доступны для основных сред IaaS.
Программная совместимость PHP 7
Помимо совместимости с инфраструктурой, вам также необходимо помнить о потенциальных проблемах совместимости программного обеспечения. Популярные системы управления контентом, такие как WordPress, Joomla и Drupal, добавили поддержку PHP 7 в своих последних выпусках. Основные фреймворки, такие как Symfony и Laravel, также пользуются полной поддержкой.
Однако пришло время предостережения. Эта поддержка не распространяется на сторонний код в виде надстроек, плагинов, пакетов или того, что ваша CMS или инфраструктура называет их. У них могут быть проблемы с совместимостью, и вы обязаны убедиться, что все готово для PHP 7.
Для активных поддерживаемых репозиториев это не должно быть проблемой. Однако старые и неподдерживаемые репозитории без поддержки PHP 7 могут сделать все ваше приложение непригодным для использования.
Будущее PHP
Выпуск PHP 7 удалил старый и устаревший код и проложил путь к новым функциям и улучшениям производительности в будущем. Кроме того, ожидается, что PHP скоро получит дополнительную оптимизацию производительности. Несмотря на некоторые проблемы с совместимостью с прошлыми версиями, большинство проблем легко решить.
Библиотеки и фреймворки сейчас переносят свой код на PHP 7, что делает доступными последние версии. Я призываю вас попробовать его и увидеть результаты для себя. Возможно, ваше приложение уже совместимо и ожидает использования PHP 7 и его преимуществ.