Состоялся релиз PHP 8.1 — языка программирования общего назначения, под управлением которого, согласно данным w3techs, работают порядка 78 % сайтов. Среди основных изменений в новой версии стоит отметить добавление перечислений, «зелёных» потоков и интерсекционных типов.
Новая функциональность
Enums
Добавлены перечисления, которые базируются на классах и объектах (поэтому оператор проверки типа instanceof
работает и с ними). Перечисления вмещают ряд констант. Но что самое важное, перечисления создают отдельный тип, с которым уже можно работать.
Пример работы с перечислениями, взятый из RFC:
enum Suit {
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
function pick_a_card(Suit $suit) { ... }
$val = Suit::Diamonds;
pick_a_card($val); // OK
pick_a_card(Suit::Clubs); // OK
pick_a_card('Spades'); // TypeError: pick_a_card(): Argument #1 ($suit) must be of type Suit, string given
Поскольку элементы перечисления объекты, то они не могут быть меньше или больше других таких элементов.
У элементов перечислений есть также свойство «name», которое хранит имя, хоть оно и является артефактом реализации, поэтому его стоит использовать для отладки.
Подкреплённые перечисления
По умолчанию элементы перечислений не имеют скалярного типа, но всё же его можно объявить при создании перечисления (доступно только для int
или string
):
enum Suit: string {
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
Такие значения называются подкреплёнными (backed), ведь значение «подкрепляются» более простым скалярным типом.
Также доступно свойство только для чтения «value», хранящее значение.
Подкреплённые перечисления реализуют интерфейс BackedEnum
, который определяет два метода:
-
from(int|string): self
принимает скалярный тип и возвращает соответствующее значение перечисления (Enum Case), а если такого нет, то будет выброшена ошибка типа ValueError; -
tryFrom(int|string): ?self
аналогичен первому методу, только теперь ошибка не будет выброшена, а просто возвратитсяnull
.
Интерфейсы, трейты и методы в перечислениях
Перечисление может вмещать методы (причём даже статические), а также использовать трейты.
Если перечисление реализует какой-то интерфейс, то все элементы перечисления пройдут проверку на тип, реализующий этот интерфейс:
interface Colorful {
public function color(): string;
}
enum Suit implements Colorful {
case Hearts;
case Diamonds;
case Clubs;
case Spades;
// Fulfills the interface contract.
public function color(): string {
return match($this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
// Not part of an interface; that's fine.
public function shape(): string {
return "Rectangle";
}
}
function paint(Colorful $c) { ... }
paint(Suit::Clubs); // Works
print Suit::Diamonds->shape(); // "rectangle"
Перечисление значений
Также перечисления реализуют метод cases()
, возвращающий список объектов перечисления:
Suit::cases();
// [Suit::Hearts, Suit::Diamonds, Suit::Clubs, Suit:Spades]
Интерсекционные типы
В противовес союзным типам в РНР 8.0, добавлена возможность указания более точных типов, путём их объединения при помощи логического «и». Это достигается благодаря комбинации имён классов или интерфейсов при помощи амперсанда &
(пример из php.watch):
function count_and_iterate(Iterator&\Countable $value) {
foreach($value as $val) {}
count($value);
}
Поддерживаются только чистые интерсекционные типы, без композиции с nullable или союзными типами. Кроме того, поддерживаются только имена классов и интерфейсов.
Нити
Добавлены файберы, предоставляющие низкоуровневый интерфейс для создания «зелёных потоков». Нити позволяют управлять параллельными процессами в пределах одного физического процесса. То есть, де-факто не будет двух участков кода, выполняющихся в один момент времени, но файберы позволяют выполнять действия в момент, пока один участок кода простаивает.
Возвращаемый тип never
Добавлена возможность объявить возвращаемый функцией тип как never
, если она всегда вызывает остановку программы. Этого можно достичь, вызывая в этой функции конструкцию exit
или die
. Пример из PHP.Watch
function redirect(string $url): never {
header('Location: ' . $url);
exit();
}
Цель этого изменения — указать, что вызов определённой функции гарантированно остановит выполнение программы.
final
для констант класса
Добавлена возможность указать константы класса итоговыми, чтобы запретить их переопределение.
class Foo {
final public const X = "foo";
}
class Bar extends Foo {
public const X = "bar";
}
// Fatal error: Bar::X cannot override final constant Foo::X
Важно заметить, что приватные константы не могут быть финальными, ведь их невозможно переопределить. Также изменено поведение переопределения констант интерфейсов. Раньше это было запрещено, теперь же разрешено, если константа не определена с ключевым словом final
.
Свойства только для чтения
Добавлена поддержка свойств классов только для чтения, значение которых можно устанавливать лишь один раз:
class Test {
public readonly string $prop;
public function __construct(string $prop) {
// Заполнение readonly-свойства
$this->prop = $prop;
}
}
$test = new Test("foobar");
// Так можно
var_dump($test->prop); // string(6) "foobar"
// А так нельзя, пускай значение и совпадает
$test->prop = "foobar";
// Error: Cannot modify readonly property Test::$prop
Ключевое слово readonly
можно использовать только с типизированным свойством. Инициализация свойства только для чтения может происходить только в классе, содержащем это свойство.
При попытке повторного установления значения или удаления переменной будет выброшено исключение типа Error
.
Кроме этого:
- Добавлены функции:
fsync
: синхронизация изменений в файле (включая метадату);fdatasync
: синхронизация изменений в файле без метадаты;array_is_list
: проверяет, является ли массив списком;- Функции для поддержки потокового шифрования
XChaCha20
в Sodium;
- Добавлено новое поле
full_path
в суперглобальном массиве$_FILES
, хранящее полный путь к файлам, который был передан браузером; - Синтаксис
first-class callable
; - Новый атрибут
#[ReturnTypeWillChange]
; - Оператор распаковки массивов теперь поддерживает массивы со строковыми ключами;
- Добавлена поддержка алгоритмов хеширования
xxHash
иMurmurHash3
; - Добавлен новый параметр
$options
для функций хеширования для определения алгоритмоспецифичных дополнительных опций; - Добавлена поддержка префикса
0o/0O
для восьмеричных чисел; - Новый класс
IntlDatePatternGenerator
, позволяющий лучше поддерживать локализованные даты; - В
phar
добавлена поддержка алгоритмов подписи OpenSSL-256 и OpenSSL-512; - В расширение
mysqli
добавлена константаMYSQLI_REFRESH_REPLICA
аналогичная уже существующей константеMYSQLI_REFRESH_SLAVE
, это сделано из-за того, что в MySQL версии 8.0.23 некоторые опции, содержащие слова «slave», были признаны устаревшимы и заменены на аналогичные с «replica». Тем не менееMYSQLI_REFRESH_SLAVE
в РНР устаревшей не признана и планов по удалению этой константы нет; - GD:
- Curl:
Изменения
Ограничение использования суперглобального массива $GLOBALS
Суперглобальный массив $GLOBALS
, хранящий пары имя_переменной => ссылка_на_переменную
больше нельзя передавать по ссылке, приравнивать его к пустому массиву или ссылке на переменную.
// Будет работать:
foreach ($GLOBALS as $var => $value) {
echo "$var => $value\n";
}
$GLOBALS['x'] = 1;
$GLOBALS['x']++;
isset($GLOBALS['x']);
unset($GLOBALS['x']);
// ...что угодно, используя $GLOBALS['x'].
// Выдаёт ошибку времени компиляции:
$GLOBALS = [];
$GLOBALS += [];
$GLOBALS =& $x;
$x =& $GLOBALS;
unset($GLOBALS);
// ...и другие подобные операции чтения-записи над $GLOBALS
// Выдаёт исключения типа Error во время исполнения:
by_ref($GLOBALS);
А также:
- Функции для работы HTML теперь будут обрабатывать одинарные кавычки
'
, а невалидные символы теперь будут просто заменены на �(U+FFFD)
; - Теперь класс
SplFixedArray
реализует интерфейсJsonSerializable
, что позволит функцииjson_encode
воспринимать его как массив; - Режим интерактивной оболочки (
php -a
) теперь требует наличия расширенияreadline
; - Функции
fputcsv
иSplFileObject::fputcsv
теперь могут принимать новый параметр, оборачивающий конец строки; - Функция
version_compare()
теперь не может принимать частичные значения для операторов; - Функция
compact()
теперь выбрасывает предупреждение, если типы её параметров отличались от массива и строки; - Разрешено использование ключевого слова
new
в параметрах функции по умолчанию, аргументах атрибутов, инициализаторах статических переменных и глобальных констант; - Благодаря изменениям в работе OPcache, производительность была повышена на 0.5-8%;
- В phar алгоритм подписи по умолчанию изменён с SHA1 на SHA256;
- Расширение MySQLi теперь использует режим выброса исключений при возникновении ошибки;
- Следующие ресурсы стали объектами:
file_info => finfo
imap => IMAP\Connection
ftp => FTP\Connection
- Функция
imageloadfont
теперь возвращает экземпляр классаGdFont
- Ресурсы
LDAP
мигрировали в экземпляры классовLDAP\Connection
,LDAP\Result
иLDAP\ResultEntry
- Ресурсы
PostgreSQL
мигрировали в экземпляры классовPgSql\Connection
,PgSql\Result
иPgSql\Lob
pspell => PSpell\Dictionary
,pspell config => PSpell\Config
Объявлено устаревшим
-
Передача
null
в параметр внутренней функции, который не поддерживаетnull
-
Переопределение внутреннего метода, когда возвращаемые типы не совпадают. Отсутствие возвращаемого типа теперь считается несовпадением типов;
-
Использование(автоматическое приведение)
false
как массива; -
Интерфейс
Serializable
; -
Неявное преобразование нецелочисленного float в int;
-
Метод
mysqli::get_client_info()
и передача параметров функцииmysqli_get_client_info()
; -
Свойство
mysqli_driver->driver_version
; -
Параметр
$num_points
функцийimageopenpolygon()
иimagefilledpolygon()
; -
Вызов перегруженых функций
pgsql
без указания соединения; -
Передача свойства
ssl_method
в конкструктор классаSoapClient
; -
Передача нестроковых параметров функциям
ctype_*()
; -
Возврат по ссылке при возвращаемом типе
void
; -
Прямой доступ к статическим элементам трейтов;
-
Передача
bool
методуIntlCalendar::roll()
; -
Вызов функции
mb_check_encoding()
без аргумента; -
Функции:
mhash*()
;strptime()
;strftime() и gmstrftime()
;odbc_result_all()
;date_sunrise()
иdate_sunset()
с соответствующими настройками в конфиге;mysqli::init()
;key(), current(), next(), prev()
иreset()
для объектов;
-
Настройки:
-
Константы:
FILTER_SANITIZE_STRING
;PDO::FETCH_SERIALIZE
;NIL
,определённая в расширении IMAP;FILE_BINARY
иFILE_TEXT
;
>>> Подробности