PHP 8.3 будет выпущен как обычно в конце ноября 2023 года.

В этом посте мы рассмотрим все функции, улучшения производительности, изменения и устаревший функционал.

/**/

Основные нововедения в php 8.3

Поправки для только для чтения

В этом RFC было предложено два изменения, но было принято только одно: возможность повторной инициализации свойств только для чтения во время клонирования.

Правда этот RFC касается только конкретного (но важного) случая: перезапись значений свойств внутри __clone(), чтобы разрешить глубокое клонирование свойств только для чтения:

readonly class Post
{
    public function __construct(
        public DateTime $createdAt,
    ) {}
    
    public function __clone()
    {
        $this->createdAt = new DateTime(); 
        // здесь это разрешено,
        // даже не смотря на то что свойство `createdAt` только для чтения.
    }
}

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

Типизированные константы класса могут быть объявлены в классах, интерфейсах, трейтах и ​​перечислениях, вы можете указать типы констант класса так:

class Foo
{
    public const string A = 'a';
    public const int B = 1;
    public const float C = 1.1;
    public const bool D = true;
    public const array E = ['a', 'b']; 
} 

Типы констант класса поддерживают все объявления типов PHP, кроме void, callable и never. 

Константы класса являются ковариантными, что означает, что их типы не могут расширяться во время наследования.

Атрибут #[Override]

Новый атрибут #[Override] используется, чтобы показать намерение программиста: «Я знаю, что этот метод переопределяет родительский метод. Если это когда-либо изменится, сообщите мне».

Вот пример:

abstract class Parent
{
    public function methodWithDefaultImplementation(): int
    {
        return 1;
    }
}

final class Child extends Parent
{
    #[Override]
    public function methodWithDefaultImplementation(): void
    {
        return 2; // The overridden method
    }
} 

Теперь давайте представим, что в какой-то момент родительский метод меняет имя своего метода: 

abstract class Parent
{
    public function methodWithNewImplementation(): int
    {
        return 1;
    }
}

Благодаря этому атрибуту #[Override] PHP сможет определить, что он больше ничего не переопределяет, и выдаст ошибку.   

Отрицательные индексы в массивах

Если у вас есть пустой массив, и вы добавите элемент с отрицательным индексом, а затем добавите еще один элемент, этот второй элемент всегда будет начинаться с индекса 0:

$array = [];

$array[-5] = 'a';
$array[] = 'b';

var_export($array);

//array (
//  -5 => 'a',
//  0 => 'b',
//)

Начиная с PHP 8.3, следующий элемент будет добавлен в index -4:

//array (
//  -5 => 'a',
//  -4 => 'b',
//)

Анонимные классы только для чтения

Ранее нельзя было пометить анонимные классы как доступные только для чтения.

Это исправлено в PHP 8.3:

$class = new readonly class {
    public function __construct(
        public string $foo = 'bar',
    ) {}
};

Новая функция json_validate

В PHP 8.3 добавлена ​​новая функция json_validate(), которая возвращает true или false в том случае, если заданная строка является допустимой строкой JSON. До PHP 8.3 единственным способом определить, является ли заданная строка допустимой строкой JSON, была попытка ее декодирования и проверка наличия каких-либо ошибок. Новая функция json_validate() использует тот же базовый синтаксический анализатор JSON, что и PHP, но потребует меньше памяти:

json_validate('[1, 2, 3]');    // true
json_validate('{1, 2, 3]');    // false

Динамический доступ к константам класса и Enum

До PHP 8.3 синтаксис доступа к константам класса типа ClassName::{$varName}  был запрещен и приводил к синтаксической ошибке:

Parse error: syntax error, unexpected token ";", expecting "(" in ... on line ...

То же ограничение применялось и к Enum, где было невозможно получить элемент Enum динамически:

Parse error: syntax error, unexpected token "->", expecting "(" in ``` on line ```

Теперь PHP 8.3 и более поздние версии поддерживают динамическое получение констант класса и объектов Enum с именем переменной:

class MyClass {
    public const MY_CONST = 42;
}

$constName = 'MY_CONST';

echo MyClass::{$constName};

Функция gc_status() возвращает дополнительную информацию GC

Функция gc_status() возвращает статистику сборщика мусора PHP и имеет четыре новых поля: running, protected, full и buffer_size: работает ли сборщик мусора, защищен ли сборщик мусора и размер буфера. Эта информация может быть полезна при отладке долго работающих PHP-приложений для обнаружения и оптимизации использования памяти.

var_dump(gc_status());

Новый метод RandomRandomizer::getBytesFromString

Класс RandomRandomizer в PHP 8.3 поддерживает новый метод getBytesFromString, который возвращает последовательность случайных чисел запрошенной длины (параметр $length), содержащую только байты из запрошенной последовательности байтов (параметр $string).

namespace Random;  

class Randomizer {  
  // ...  
   public function getBytesFromString(string $string, int $length): string { }
 }
 
$rng = new RandomRandomizer();
$crockfordAlphabet = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';

$rng->getBytesFromString($crockfordAlphabet, 5); // "5YH8T"

Новые методы RandomRandomizer::getFloat() и nextFloat() 

RFC добавляет новые методы в расширении Random, генерирующие случайное значение. RandomRandomizer::getFloat(), RandomRandomizer::nextFloat(). Например если необходимо сгенерировать случайное число float между 0 <и < 10 и в диапазоне 0 <= и < 1:

$rng = new RandomRandomizer();
$rng->getFloat(0, 10, RandomIntervalBoundary::OpenOpen); // 9.3835746900717

...

$rng = new RandomRandomizer();
$rng->nextFloat(); // 0.21185336351144

Более подходящие исключения даты/времени

Во многих случаях PHP просто выбрасывал объект Exception или Error или выдавал предупреждение/ошибку, когда что-то пошло не так при работе с датами и временем. Этот RFC добавляет для них соответствующие специальные исключения.

Теперь у нас есть исключения, такие как DateMalformedIntervalStringException, DateInvalidOperationException и DateRangeError.

Как правило, эти дополнения не нарушают код, поскольку эти недавно добавленные исключения и ошибки являются подклассами общего Exception/Error классов. Однако в этом RFC есть три небольших критических изменения:

  • Теперь Epoch doesn't fit in a PHP integer возвращает new DateRangeError вместо ValueError, который не является подклассом. Это проблема только для 32-битных платформ.

  • Предупреждение Only non-special relative time specifications are supported for subtraction становится новым DateTime::sub() date_sub() DateInvalidOperationException

  • Предупреждения Unknown or bad format (%s) at position %d (%c): %sи String '%s' contains non-relative elements, которые создаются при анализе неправильных/битых DateInterval строк, теперь будут выдавать новое исключение DateMalformedIntervalStringException при использовании с интерфейсом OO вместо отображения предупреждения и возврата false.

Функция unserialize(): Вывод E_WARNING ошибок вместо E_NOTICE

До версии PHP 8.3 передача недопустимой строки в функцию unserialize() выдавала всего лишь уведомления PHP ( E_NOTICE) в определенных случаях, например, при синтаксических ошибках в сериализованной строке. Начиная с PHP 8.3 выдается предупреждение E_WARNING. Кроме того, некоторые условия ошибки так же изменились в функции serialize(), чтобы выдать E_WARNING:

unserialize("invalid-string");

 - PHP Notice:  unserialize(): Error at offset 0 of 14 bytes // было
 + PHP Warning:  unserialize(): Error at offset 0 of 14 bytes // стало

В идеале невозможность десериализации данной строки должна быть серьезной ошибкой и вызывать исключение. Однако для обеспечения обратной совместимости и упрощения путей обновления уровень ошибок в PHP 8.3 был увеличен, а в будущем возможно его обновление для создания исключений.

Трейты и статические свойства

Использование трейтов со статическими свойствами теперь будет повторно объявлять статические свойства, унаследованные от родительского класса.

Это создаст отдельное хранилище статических свойств для текущего класса. Это аналогично добавлению статического свойства в класс напрямую без трейтов.

Обнаружение переполнения стека

В PHP 8.3 добавлены две новые директивы ini с именами zend.max_allowed_stack_size и zend.reserved_stack_size. Приложения, близкие к переполнению стека вызовов, теперь могут вызывать Error при использовании больше, чем разница между zend.max_allowed_stack_size и zend.reserved_stack_size.

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

Значение по умолчанию для zend.max_allowed_stack_size равно 0, что означает, что PHP автоматически определит значение. Вы также можете указать -1, что ограничений нет или указать определенное количество байтов. Директива zend.reserved_stack_size используется для определения «буферной зоны», так что PHP может по-прежнему выдавать ошибку вместо того, чтобы фактически исчерпать память. Значение здесь должно быть числом байтов, но PHP сам определит для вас разумное значение по умолчанию, поэтому вам не обязательно устанавливать его, если только вы не сталкиваетесь с пограничными случаями для конкретных приложений.

И наконец, для файберов в качестве максимально допустимого размера стека используется существующая директива fiber.stack_size .

zend.max_allowed_stack_size=128K

Функция class_alias() поддерживает псевдонимы встроенных классов PHP

Функция class_alias создает псевдоним для предоставленного класса. Класс с псевдонимом ведет себя точно так же, как исходный класс.

Но до PHP 8.3 попытка создать псевдоним для встроенного класса PHP приводила к исключению ValueError:

class_alias('stdClass', 'MyClass'); 
class_alias('Traversable', 'NewTraversableInterface');

ValueError: class_alias(): Argument #1 ($class) must be a user-defined class name, internal class name given

Начиная с PHP 8.3 можно использовать псевдонимы для встроенных классов и интерфейсов и код отработает корректно:

class_alias('stdClass', 'MyClass'); 
class_alias('Traversable', 'NewTraversableInterface');

Функция class_alias() принимает bool $autoload = true в качестве третьего параметра. Этот параметр не влияет на встроенные классы, поскольку их не нужно загружать автоматически.

Небольшие, но заметные изменения

И как обычно, не каждое изменение в PHP проходит процесс RFC. На самом деле, большинство изменений включают обслуживание и исправление ошибок и не требуют RFC. Все эти изменения перечислены в документе ОБНОВЛЕНИЕ . Я перечислю некоторые из самых известных, но вам обязательно следует прочитать весь список, если вы хотите узнать о мельчайших деталях.

  • При использовании FFI функции C, которые имеют возвращаемый тип void теперь возвращают null вместо FFICData:void

  • posix_getrlimit() теперь принимает необязательный параметр $res, позволяющий получить ограничение на один ресурс.

  • mysqli_poll() теперь выдает ValueError, когда передаются аргументы чтения или ошибки.

  • array_pad() теперь ограничено только максимальным количеством элементов, которые может иметь массив. Раньше можно было добавить не более 1048576 элементов за раз.

  • Новые функции posix: posix_sysconf(), posix_pathconf(), posix_fpathconf() и posix_eaccess()

  • proc_get_status() многократное выполнение теперь всегда будет возвращать правильное значение в posix-системах.


Источники

Tags

Нет Ответов

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Рубрики


Подпишись на новости
👋

Есть вопросы?