PHP 7.3 - Основные нововведения

2018-12-15
PHP

6 декабря 2018 года вышел минорный релиз PHP 7.3. Далее, в порядке от более важного к менее важному, будут кратко рассмотрены основные нововведения в данном релизе PHP.

Выброс исключений при ошибках в функциях json_encode() и json_decode()

Если раньше нужно было использовать ф-ю json_last_error(), то теперь можно просто отлавливать исключения. Для этого в функциях json_encode() и json_decode() нужно предавать специальную новую константу JSON_THROW_ON_ERROR:

try {
    json_encode('some invalid data...', JSON_THROW_ON_ERROR);
    json_decode('{', false, 512, JSON_THROW_ON_ERROR); 
} catch (\JsonException $exception) { 
    echo $exception->getMessage();
}
Результат: "Syntax error"

Новый \JsonException является наследником от \Exception. Константа JSON_THROW_ON_ERROR и сам JsonException находятся в глобальном пространстве имен.

Новые функции array_key_first() и array_key_last()

array_key_first() - Возвращает первый ключ массива.
array_key_last() - Возвращает последний ключ массива.

$colors = [
    'ff0000' => 'red',
    '00ff00' => 'green',
    '0000ff' => 'blue',
];

echo array_key_first($colors) . PHP_EOL;
echo array_key_last($colors);
Результат:

ff0000
0000ff

Миграция с PCRE на PCRE2

PHP использует Perl Compatible Regular Expressions или коротко PCRE в библиотеке для работы с регулярными выражениями. С версии PHP 7.2 используется 8.x версия устаревшей библиотеки PCRE, а в PHP 7.3 уже используется PCRE2. Обратите внимание, что PCRE2 считается новой библиотекой, хотя в значительной степени совместима с PCRE (8.x). Новая библиотека более агрессивна к проверке регулярных выражений и может привести к ошибкам в существующем коде, который на более ранних версиях PHP работал стабильно.

Ссылки в list()

В версии PHP 7.3 стало возможным передать элемент массива по ссылке используя list():

$colors = ['red', 'green'];
list($a, &$b) = $colors;
$b = 'blue';
echo $colors[1];
Результат: blue

Также вместо ф-и list()можно использовать альтернативный синтаксис с квадратными скобками:

$colors = ['red', 'green'];
[$a, &$b] = $colors; // <--
$b = 'blue';
echo $colors[1];
Результат: blue

Регистро-независимые константы объявлены устаревшими

Ранее функция define() позволяла объявить константу в регистро-независимом режиме. Для этого необходимо было явно объявить константу как регистро-независимую, передав третьим параметром true:

define('Red', 'ff0000', true);

Теперь, приведенный выше код будет выбрасывать уведомление:

Deprecated: define(): Declaration of case-insensitive constants is deprecated in ...

Поэтому дальнейшее использование регистро-независимых констант не рекомендуется, т.к. в дальнейших релизах PHP оно скорее всего вообще будет запрещено.

Добавление функции is_countable()

countable-переменной является массив или объект реализующий \Countable интерфейс. В PHP 7.3 появилась новая функция is_countable(), проверяющая переменную на возможность использования с функцией count():

$a = 1;
$b = [1, 2, 3];
var_dump(is_countable($a), is_countable($b));
Результат: bool(false) bool(true)

Поддержка конечных запятых в вызовах функций и методов

Теперь разрешено использование конечных запятых в вызовах функций и методах:

function sum($a, $b) {
    return $a + $b;
}

echo sum(2, 2,); // <-- запятая в конце не вызовет ошибку
Результат: 4

Обратите внимание, что нельзя использовать эту возможность в объявлениях функций/методов:

function sum($a, $b,) { // <-- тут запятую в конце ставить нельзя
}
Результат: Parse error: syntax error, unexpected ')', expecting variable (T_VARIABLE) in ...

Выброс Notice при использовании не определенной переменной в ф-и compact()

Теперь при передаче в ф-ю compact() неопределенной переменой, выбрасывается Notice:

$someVars = compact('someUndefinedVar');
Результат: Notice: compact(): Undefined variable: someUndefinedVar

Улучшения хеширования паролей с помощью алгоритма Argon2

Алгоритм Argon2 имеет три варианта хеширования: Argon2i, Argon2d и Argon2id.

Argon2d работает быстрее и использует зависящий от данных доступ к памяти, что делает его очень устойчивым к атакам с крекингами GPU и подходит для приложений без угроз от атак со сторонних каналов (например, криптовалюты).

Argon2i использует независимый от данных доступ к памяти, который предпочтительнее для хеширования паролей но медленнее, поскольку для защиты от атак делает больше проходов по памяти.

Argon2id является гибридом Argon2i и Argon2d, и использует комбинацию доступа к данным, зависящим и не зависящим от данных, что дает некоторую устойчивость Argon2i к атакам на кеш-сервер и большую часть устойчивости Argon2d к атакам крекинга GPU.

Нововведение добавляет поддержку алгоритма хеширования Argon2id в функциях password_*, добавлена новая константа PASSWORD_ARGON2ID:

$somePasswordHashed = password_hash('123456', PASSWORD_ARGON2ID);
var_dump(password_verify('123456', $somePasswordHashed));
Результат: bool(true)

Смягчение требований к синтаксису Heredoc и Nowdoc

Heredoc и Nowdoc требовали ставить закрывающий идентификатор первым в новой строке. Теперь эти требования убраны. Это сделано для улучшения читабельности кода, прежде всего чтобы можно было добавлять отступы при использовании Heredoc/Nowdoc идентификаторов:

$text = <<<IDENTIFIER        
        Some        
        long        
        text...        
        IDENTIFIER;

echo $text;
Результат:

Some
long
text...

Массив опций в функциях для работы с Cookie

В функциях setcookie(), setrawcookie() и session_set_cookie_params() параметры, используемые в заголовке: Set-Cookie, path, domain, secure и httponly - перемещены в параметр $options. При этом текущий вариант реализации, где каждый параметр является отдельным аргументом, остается работоспособным:

bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false]]]]]] );
bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, array $options ]]] );

bool setrawcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false]]]]]] );
bool setrawcookie ( string $name [, string $value = "" [, int $expire = 0 [, array $options ]]] );

void session_set_cookie_params ( int $lifetime [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]] );
void session_set_cookie_params ( int $lifetime [, array $options ] );

По-умолчанию параметр $options равен пустой строке. Стандартные значения в этих ф-ях остаются без изменений.

Функция image2wbmp() объявлена устаревшей

Функция image2wbmp() из расширения GD использовалась для вывода изображения в формате WBMP (Wireless Bitmap). Теперь она объявлена устаревшей в пользу функции imagewbmp().

Флаги FILTER_FLAG_SCHEME_REQUIRED и FILTER_FLAG_HOST_REQUIRED при использовании FILTER_VALIDATE_URL объявлены устаревшими

Когда используется ф-я filter_var($var, FILTER_VALIDATE_URL), есть два дополнительных флага, которые можно поставить для обеспечения строгой проверки URL-адреса: FILTER_FLAG_SCHEME_REQUIRED и FILTER_FLAG_HOST_REQUIRED. Теперь их использовать запрещено, т.к. их роль по сути и так выполняет константа FILTER_VALIDATE_URL.

Прочие изменения

Добавлено новое исключение CompileError, наследуемое от ParseError и генерирующее для некоторых типов ошибок перехватываемое событие CompileError вместо фатальной ошибки.

Значительно расширены возможности и увеличена производительность дополнения MBString, в том числе добавлены полноценные средства для манипуляций с регистром символов (MB_CASE_LOWER, MB_CASE_UPPER, MB_CASE_TITLE, MB_CASE_FOLD и т.п.), до версии 11 обновлена поддержка спецификаций Unicode, добавлена поддержка строк, размером больше 2 Гб, в функциях mb_ereg_*() добавлена поддержка именованного захвата элементов. Объявлены устаревшими вызовы mbereg_*(), вместо которых следует использовать mb_ereg_*().

В SAPI-модуль FPM добавлены новые глобальные опции log_limit и log_buffering для ограничения размера выводимой в лог строки и включения режима записи в лог без буферизации. Также добавлена опция decorate_workers_output, позволяющая отключить декорирование вывода от рабочих процессов при активации режима catch_workers_output.

В расширении LDAP в большинстве функций, таких как ldap_add и ldap_read, появился параметр serverctrls для отправки на сервер дополнительных сообщений (LDAP Controls - механизм расширения операций LDAP и передачи дополнительной информации вместе с запросом), а в ldap_parse_result для получения клиентом дополнительных сообщений от сервера. Налажена поддержка режимов LDAP_OPT_SERVER_CONTROLS и LDAP_OPT_CLIENT_CONTROLS в функциях ldap_get_option и ldap_set_option.

В расширение GD в функции imagecreatefromstring() появилась поддержка создания изображений в формате WebP.

Представлена новая функция net_get_interfaces() для получения информации о доступных сетевых интерфейсах.

Улучшена работа сборщика мусора.

Приведены к соответствию с поведением Unix операции открытия файлов в Windows: файловые дескрипторы теперь по умолчанию открываются в Windows в режиме, допускающем чтение, запись и удаление (открытые файлы теперь можно удалить).

Ссылки по теме

PHP 7.3.0 Release Announcement
PHP ChangeLog Version 7.3.0
RFC PHP 7.3
Миграция с PHP 7.2.x на PHP 7.3.x
PCRE Syntax Man Page (старый)
PCRE2 Syntax Man Page (новый)
PHP 7.3: Изменения / GTXTYMT
Релиз языка программирования PHP 7.3 / OpenNET