PHP 7.4 - последняя версия перед PHP 8, содержит множество дополнений и исправлений синтаксиса, будет выпущен 28 ноября 2019 года. Пост создан для помощи в подготовки к предстоящим изменениям.
PHP 7.4 будет содержать немало новых возможностей, начнем с новых функций, а затем рассмотрим изменения и устаревание функционала.
Короткие замыкания допускают менее подробный синтаксис анонимной функции. Вместо многословного:
array_map(function (User $user) {
return $user->id;
}, $users)
можно использовать более лаконичное выражение:
array_map(fn(User $user) => $user->id, $users)
Согласитесь, выглядит здорово?!
Несколько замечаний:
Предварительная загрузка - удивительное дополнение к ядру PHP, которое может привести к значительному улучшению производительности.
Итак, если вы в своей работе используете какой-либо фреймворк, его файлы должны быть загружены и перекомпилированы при каждом запросе. Предварительная загрузка позволяет серверу загружать PHP-файлы в память при запуске и иметь их постоянно доступными для всех последующих запросов.
Предварительная загрузка управляется директивой opcache.preload в файле php.ini. Эта директива указывает PHP-скрипт, который будет скомпилирован и выполнен при запуске сервера. Данный файл может использоваться для предварительной загрузки дополнительных файлов или через функцию opcache_compile_file() (подробнее см. Документацию PHP).
Повышение производительности, конечно, связано с некоторым условием: если источник предварительно загруженных файлов изменяется, сервер должен быть перезапущен.
Переменные класса могут быть подсказаны типом:
<?php
class A
{
public string $name;
public Foo $foo;
}
Это очень долгожданное со времён PHP 7 изменение в направлении более строгой типизации языка. Теперь у нас есть все основные возможности для строгой типизации.Для типизации доступны все типы, за исключением void и callable.
Разница типов - это тема, достойная отдельного сообщения в блоге ; короче говоря: вы сможете использовать противоречивые типы возврата
class ParentType {}
class ChildType extends ParentType {}
class A
{
public function covariantReturnTypes(): ParentType
{ /* … */ }
}
class B extends A
{
public function covariantReturnTypes(): ChildType
{ /* … */ }
}
... и противоречивые аргументы.
class A
{
public function contraVariantArguments(ChildType $type)
{ /* … */ }
}
class B extends A
{
public function contraVariantArguments(ParentType $type)
{ /* … */ }
}
RFC в настоящее время находится на этапе голосования, но, похоже, пройдет без проблем
Интерфейс внешней функции, FFI, позволяет вызывать код C из пользовательского пространства. Это означает, что расширения PHP могут быть написаны на чистом PHP.
Следует отметить, что это сложная тема. Вам все еще нужны знания C, чтобы правильно использовать эту функцию.
Появится возможность использовать синтаксис "если левый параметр не существует или равен null, присвоить ему значение правого параметра".
Т.е. вместо этого:
$data['date'] = $data['date'] ?? new DateTime();
Вы можете сделать это:
$data['date'] ??= new DateTime();
Теперь можно использовать оператор распаковки в массивах:
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3]
Это работает только с массивами с числовыми ключами, с ассоциативными массивами распаковка работать не будет, ошибка будет выдана при обнаружении строкового ключа. Оператор спреда должен иметь лучшую производительность, чем array_merge. Это объясняется не только тем, что оператор распаковки является языковой структурой, в то время как array_merge является функцией, но и оптимизация времени компиляции может быть выполнена для констант массива. Плюс array_merge поддерживает операции только над массивами, а оператор спреда поддерживает реализацию объектов Traversable.
В настоящее время PHP предоставляет два механизма для настраиваемой сериализации объектов: методы __sleep()/__wakeup() и Serializable интерфейс. К сожалению, по словам Никиты, оба подхода имеют проблемы., которые приводят к сложному и ненадежному коду Этот RFC добавляет два новых магических метода: __serialize и __unserialize, которые позволяют избежать этих проблем
// Returns array containing all the necessary state of the object.
public function __serialize(): array;
// Restores the object state from the given data array.
public function __unserialize(array $data): void;
Использование очень похоже на Serializable интерфейс. С практической точки зрения главное отличие состоит в том, что вместо вызова serialize() внутри Serializable::serialize() вы напрямую возвращаете данные, которые должны быть сериализованы в виде массива. В следующем примере показано, как __serialize()/__unserialize() используются и как они составляются при наследовании:
class A {
private $prop_a;
public function __serialize(): array {
return ["prop_a" => $this->prop_a];
}
public function __unserialize(array $data) {
$this->prop_a = $data["prop_a"];
}
}
class B extends A {
private $prop_b;
public function __serialize(): array {
return [
"prop_b" => $this->prop_b,
"parent_data" => parent::__serialize(),
];
}
public function __unserialize(array $data) {
parent::__unserialize($data["parent_data"]);
$this->prop_b = $data["prop_b"];
}
}
Разделитель числовых литералов RFC
Отсутствие визуальных разделителей в группах цифр увеличивало время чтения и отладки кода, и могло привести к непреднамеренным ошибкам. Теперь добавлена поддержка символа подчёркивания в числовых литералах для визуального разделения групп цифр.
1_000_000_000 // int
6.674_083e-11; // float
299_792_458; // decimal
0xCAFE_F00D; // hexadecimal
0b0101_1111; // binary
0137_041; // octal
Такие библиотеки как var dumper Symfony, в значительной степени полагаются на API Рефлексии для надежного вывода переменной. Раньше не было должной поддержки рефлексии для ссылок, в результате чего эти библиотеки полагались на "хаки" для обнаружения ссылок.
PHP 7.4 добавляет класс ReflectionReference, который решает эту проблему.
Обновление 02-14: RFC пройден, и изменения подтверждены для PHP 7.4.
Слабые ссылки - это ссылки на объекты, которые не мешают их уничтожению. PHP 7.4 вводит класс WeakReference , который позволяет программистам сохранять ссылку на объект, который не препятствует уничтожению самого объекта. В настоящее время PHP поддерживает Weak References, используя расширение вроде pecl-weakref . В любом случае, новый API отличается от документированного WeakRefкласса.
Вот пример от автора этого предложения, Никиты Попова:
$object = new stdClass;
$weakRef = WeakReference::create($object);
var_dump($weakRef->get());
unset($object);
var_dump($weakRef->get());
Сначала var_dump выведет object(stdClass)#1 (0) {} , а потом выведет NULL , так как указанный объект был уничтожен.
Эта функция обеспечивает те же функциональные возможности, что str_split и для многобайтовых строк.
Внутренние изменения в библиотеке хеширования, чтобы пользователям было проще использовать хэширование. Добавлена новая функция password_algos, которая возвращает список всех зарегистрированных алгоритмов хеширования паролей
Изменения и устаревание
Помимо новых функций, есть также много изменений в языке. Большинство этих изменений не нарушают работу программиста, хотя некоторые из них могут повлиять на уже написанный вами код.
Обратите внимание, что предупреждения об устаревании не являются критическими, а просто уведомляют разработчика о том, что функциональность будет удалена или изменена в будущем. Было бы хорошо не игнорировать предупреждения об устаревании и сразу же их исправлять; поскольку это сделает путь обновления для PHP 8.0 более простым.
Если бы вы написали что-то вроде этого:
echo "sum: " . $a + $b;
PHP ранее интерпретировал бы это так:
echo ("sum: " . $a) + $b;
PHP 8 сделает так, чтобы он интерпретировался так:
echo "sum :" . ($a + $b);
В PHP 7.4 при обнаружении выражения без скобок, добавлено предупреждение об устаревании синтаксиса, содержащего «.» перед «+» или «-».
Ранее исключения не могли быть добавлены в магический метод__toString. Они были запрещены из-за некоторых старых механизмов обработки ошибок, правда Никита Попов отметил, что это «решение» на самом деле не решило проблему, которую он пытался решить.
RFC все еще находится на стадии голосования, но с 32 голосами за и 0 против, можно с уверенностью сказать, что это пройдет.
ext-hash всегда включен RFC
Как видно из заголовка, это расширение теперь постоянно доступно во всех установках PHP.
Поскольку PEAR больше не поддерживается, основная команда решила удалить установку по умолчанию с PHP 7.4.
Устареет ext/wwdx RFC
Этот формат обмена данными никогда не был стандартизирован, и теперь его расширение устарело.
Короткий открытый тег <? устарел и будет удален в PHP 8. Короткий echo тег <?= оставлен.
array_merge и array_merge_recursive без аргументов
Поскольку добавлен оператор распаковки (...), теперь имеет смысл использовать array_merge так:
$merged = array_merge(...$arrayOfArrays);
Теперь array_merge и array_merge_recursive позволяют передавать пустой список параметров. Пустой массив будет возвращен, если не было передано ни одного массива.
Ранее несколько тегов можно было бы удалить только перечислением тегов в строке:
strip_tags($string, '<a><p>')
PHP 7.4 позволяет использовать массив:
strip_tags($string, ['a', 'p'])
Тернарный оператор имеет некоторые странные особенности в PHP. Этот RFC добавляет статус деприкейт для вложенных троичных операторов. В PHP 8 это устаревание будет преобразовано в ошибку времени при компиляции.
//устареет
1 ? 2 : 3 ? 4 : 5;
//нормально
(1 ? 2 : 3) ? 4 : 5;
Раньше можно было получить доступ к массивам и смещениям строк, используя фигурные скобки:
$array{1};
$string{3};
Теперь лучше от этого отказаться.
Были внесены изменения, чтобы proc_open мог выполнять программы, не проходя через shell. Это делается путем передачи массива вместо строки для команды.
Обратно несовместимые изменения
Так же не забываем смотреть на полный документ обновлений версий PHP.
Можно выделить следующие несовместимых назад изменений:
Технически это не обновление, связанное с PHP 7.4, хотя это, безусловно, стоит упомянуть. Правила голосования для RFC были изменены: для принятия RFC требуется 2/3 голосов, все RFC должны быть открыты не менее 2 недель, чтобы пройти одобрение.
Веб-разработчик со стажем программирования более 13 лет, постоянно учусь, люблю делать новые проекты.