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

Ядро 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 {}
}

?>
Полная поддержка вариантности доступна только при автозагрузке классов. Нельзя ссылаться на типы циклически внутри одного файла, поскольку при ссылке на класс, который пока недоступен, возникает фатальная ошибка.
<?php

/**
* Класс удовлетворяет принципу подстановки Б. Ли́сков (англ. Liskov Substitution Principle, LSP),
* поскольку класс C принадлежит подтипу A,
* но при объявлении класса B класс C ещё недоступен
*/
class A
{
public function
method(): A {}
}

class
B extends A
{
// Fatal error: Could not check compatibility between B::method():C and
// A::method(): A, because class С is not available
public function method(): С {}
}

class
C extends B {}

?>

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

<?php

$array
['key'] ??= computeDefault();

// Предыдущая проверка на null с присваиванием — примерно то же, что:
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

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

Модуль FFI

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

Модуль GD

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

Модуль Hash

Добавили поддержку алгоритма 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) методы PDO::errorInfo() и PDOStatement::errorInfo() возвращают расширенные коды ошибок СУБД SQLite3.

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() стали поддерживать вызов без аргументов. При вызове без аргументов функции возвращают пустой массив. Функции также полезно вызывать с распаковкой аргумента spread-оператором: 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 и argon2id без библиотеки libargon

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

Добавить

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

up
98
Rain
5 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
5 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