PHP 8.4.1 Released!

Новые возможности

Ядро PHP

Типизированные свойства

Свойства класса теперь поддерживают объявления типов.

<?php
class User {
public
int $id;
public
string $name;
}
?>
В приведённом примере выше показано, что $user->id можно присвоить только значения типа int, когда как $user->name - исключительно значения типа string.

Стрелочные функции

Стрелочные функции - это сокращённая запись для определения функций с неявной привязкой родительской области видимости по значению.

<?php
$factor
= 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>

Ограниченная ковариация возвращаемого типа и контравариантность типа аргумента

Следующий код теперь будет работать:

<?php
class A {}
class
B extends A {}

class
Producer {
public function
method(): A {}
}
class
ChildProducer extends Producer {
public function
method(): B {}
}
?>
Полная поддержка вариантности доступна только при использовании автозагрузки. Внутри одного файла могут быть только нециклические ссылки, поскольку все классы должны быть определены, перед тем как на них ссылаться.

Присваивающий оператор объединения с null

<?php
$array
['key'] ??= computeDefault();
// примерно то же самое
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>

Распаковка внутри массивов

<?php
$parts
= ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
?>

Разделитель в числовых литералах

Теперь в числовых литералах между знаками могут быть символы подчёркивания.

<?php
6.674_083e-11
; // число с плавающей точкой
299_792_458; // десятичное число
0xCAFE_F00D; // шестнадцатеричное число
0b0101_1111; // двоичное число
?>

Слабые ссылки

Слабые ссылки позволяют программисту сохранить ссылку на объект, которая не помешает сборщику мусора удалить этот объект.

Обработка исключений из метода __toString()

Выбрасывание исключений из метода __toString() теперь разрешено. Ранее это приводило к фатальной ошибке. Существующие отлавливаемые фатальные ошибки при преобразовании объекта в строку будут доступны в виде исключений класса Error.

CURL

Помимо обычных имён файлов, класс CURLFile теперь поддерживает потоковые обёртки, если модуль был собран с версией libcurl >= 7.56.0.

Фильтрация

Фильтр FILTER_VALIDATE_FLOAT теперь поддерживает параметры min_range и max_range, с тем же смыслом, что и для FILTER_VALIDATE_INT.

FFI

FFI - новый модуль, который предлагает простой способ вызова встроенных функций, доступа к встроенным переменным, а также создавать или обращаться к структурам данных в библиотеках на языке Си.

GD

Добавлена константа IMG_FILTER_SCATTER для применения рассеивающегося фильтра к изображениям.

Хеширование

Добавлен хеш crc32c, использующий полином Кастаноли. Эта реализация алгоритма CRC32 используется системами хранения, такими как iSCSI, SCTP, Btrfs и ext4.

Многобайтовые строки

Добавлена функция mb_str_split(), которая выполняет, то же, что и str_split(), но работает с кодовыми точками, а не с байтами.

OPcache

Добавлена поддержка предварительной загрузки кода.

Регулярные выражения (совместимые с Perl)

Функции preg_replace_callback() и preg_replace_callback_array() теперь принимают дополнительный аргумент flags с поддержкой флагов PREG_OFFSET_CAPTURE и PREG_UNMATCHED_AS_NULL. Он повлияет на формат массива совпавших значений, передаваемого в callback-функцию.

PDO

Имя пользователя и пароль теперь можно указать как часть DSN для драйверов mysql, mssql, sybase, dblib, firebird и oci. Ранее поддержка этого была только для драйвера pgsql. Если имя пользователя/пароль указаны и в конструкторе и в DSN, то конструктор будет иметь приоритет.

Также теперь можно экранировать вопросительные знаки в SQL-запросах, чтобы они не воспринимались как именованные параметры. Использование ?? отправит один знак вопроса в базу данных, и, например, в случае использования PostgreSQL, будет использован оператор проверки существования ключа в JSON (?).

PDO_OCI

Для данного драйвера теперь доступен метод PDOStatement::getColumnMeta().

PDO_SQLite

Выражение PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) позволяет проверить, доступен ли подготовленный запрос только для чтения, т.е. не изменяет ли он базу данных.

PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true) позволяет использовать расширенные коды результата SQLite3 в PDOStatement::errorInfo().

SQLite3

Добавлен метод SQLite3::lastExtendedErrorCode() для получения последнего расширенного кода результата.

Добавлен метод SQLite3::enableExtendedResultCodes($enable = true), который заставит метод SQLite3::lastErrorCode() возвращать расширенные коды результаты.

Стандартное

strip_tags() с массивом имён тегов

Функция strip_tags() теперь также принимает массив разрешённых тегов: вместо strip_tags($str, '<a><p>') теперь можно написать strip_tags($str, ['a', 'p']).

Пользовательская сериализация объектов

Добавлен новый механизм сериализации пользовательских объектов, использующий два новых магических метода: __serialize и __unserialize.

<?php
// Возвращает массив, содержащий все необходимое состояние объекта.
public function __serialize(): array;

// Восстанавливает состояние объекта из указанного массива данных.
public function __unserialize(array $data): void;
?>
Новый механизм сериализации заменяет интерфейс Serializable, который в будущем будет объявлен устаревшим.

Функции слияния массивов без аргументов

Функции array_merge() и array_merge_recursive() теперь могут вызываться без каких-либо аргументов, и тогда они возвратят пустой массив. Это полезно в сочетании с оператором расширения, например, array_merge(...$arrays).

Функция proc_open()

proc_open() теперь принимает массив вместо строки для выполнения команды. В этом случае процесс будет открыт напрямую (без командной оболочки), а PHP экранирует любой необходимый аргумент.

<?php
proc_open
(['php', '-r', 'echo "Привет, мир\n";'], $descriptors, $pipes);
?>

Функция proc_open() теперь поддерживает дескрипторы redirect и null.

<?php
// То же самое, что и 2>&1 в командной оболочке
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes);
// То же самое, что и 2>/dev/null или 2>nul в командной оболочке
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);
?>

argon2i(d) без libargon

Функция password_hash() теперь поддерживает варианты хеширования argon2i и argon2id из модуля sodium, когда PHP собран без libargon.

Добавить

Примечания пользователей 2 notes

up
98
Rain
4 years ago
It should be noted that typed properties internally are never initialized to a default null. Unless of course you initialize them to null yourself. That's why you will always going to encounter this error if you try to access them before initialization.

**Typed property foo::$bar must not be accessed before initialization**

<?php
class User
{
public
$id;
public
string $name; // Typed property (Uninitialized)
public ?string $age = null; // Typed property (Initialized)
}

$user = new User;
var_dump(is_null($user->id)); // bool(true)
var_dump(is_null($user->name)); // PHP Fatal error: Typed property User::$name must not be accessed before initialization
var_dump(is_null($user->age));// bool(true)
?>

Another thing worth noting is that it's not possible to initialize a property of type object to anything other than null. Since the evaluation of properties happens at compile-time and object instantiation happens at runtime. One last thing, callable type is not supported due to its context-dependent behavior.
up
7
wow-apps.pro
4 years ago
<?php

// How to get property type? For example for testing:

class Foo
{
private
int $num;
private
bool $isPositive;
private
$notes;
}

$reflection = new \ReflectionClass(Foo::class);
$classProperties = $reflection->getProperties(\ReflectionProperty::IS_PRIVATE);
foreach (
$classProperties as $classProperty) {
var_dump((string) $classProperty->getType());
}

/**
* Result:
* "int"
* "bool"
* ""
*/
To Top