PHP 12835 ~ 13 мин.

Что нового в PHP 8.4

Что нового в PHP 8.4

PHP 8.4, был выпущен 21 ноября 2024 года

Когда выйдет PHP 8.4?

PHP 8.4, был официально выпущен 21 ноября 2024 года. Данный пост будет пополняться новыми функциями и устареваниями по мере появления RFC. 

Как установить и протестировать PHP 8.4?

На сегодняшний день не существует простого способа установить PHP 8.4. Как появится ветка версии 8.4 можно будет скомпилировать его из исходного кода.

Новый JIT-движок

Как вы знаете JIT появился в PHP 8.0 и представлял из себя компиляцию "на лету" - Just In Time, в PHP 8.4 будет новый JIT-движок. Теперь это настоящий оптимизирующий компилятор с промежуточным представлением, аналогичный серверному компилятору Java HotSpot

phpinfo отображает информации о размере целочисленного типа (int) PR

Вывод phpinfo() в PHP 8.4 показывает размер целого числа, поддерживаемый текущей настройкой PHP в битах, также включается в выходные данные PHP CLI:

Ранее все предыдущие версии (начиная с PHP 5.0.5) поддерживали константы PHP_INT_SIZE для определения размера целого числа.

Поддержка AEGIS-128L и AEGIS256 в Sodium

AEGIS - это семейство алгоритмов шифрования с проверкой подлинности на основе AES, которые работают быстрее, чем AES-GCM. Расширение Sodium в PHP 8.4 поддерживает алгоритмы шифрования AEGIS-128L и AEGIS256, если расширение Sodium скомпилировано с версией libsodium 1.0.19 или новее. Расширение Sodium в PHP 8.4 добавляет шесть новых функций и четыре новые константы PHP для AEGIS-128L и AEGIS-256AEAD.

Новые функции array_find, array_find_key, array_any, array_all RFC

В PHP 8.4 добавлены четыре новые функции для работы с массивами, для поиска и проверки элементов с помощью функции обратного вызова:

  • array_find - Возвращает значение первого элемента из массива, для которого возвращается результат callback = true;

  • array_find_key - Возвращает ключ первого элемента из массива, для которого возвращается результат callback = true;

  • array_all - Возвращает true, если все элементы в массиве соответствует условию callback

  • array_any - Возвращает true, если хотя бы один элемент в массиве соответствует условию callback

function isEven(int $value): bool {
    return $value % 2 === 0;
}

array_find([1, 2, 3, 4, 5], 'isEven');
// 2

...

function isEven(int $value): bool {
    return $value % 2 === 0;
}

array_find_key(['foo' => 1, 'bar' => 2, 'baz' => 3], 'isEven');
// "bar"

...

array_all(
    ['foo@example.com', 'bar@example.com', 'baz@example.com'],
    fn($value) => filter_var($value, FILTER_VALIDATE_EMAIL),
);
// true

...

array_any(
    ['foo@example.com', 'https://sergeymukhin.com', 'foobar'],
    fn($value) => filter_var($value, FILTER_VALIDATE_URL),
);
// true

Новые константы для Curl CURL_HTTP_VERSION_3 и CURL_HTTP_VERSION_3ONLY для поддержки HTTP/3

Расширение PHP Curl способно выполнять HTTP-запросы HTTP/3 (также известный как QUIC), если расширение Curl скомпилировано с необходимыми зависимостями для HTTP/3. В PHP 8.4 расширение Curl объявляет две следующие новые константы PHP, которые являются принятыми параметрами для CURLOPT_HTTP_VERSIONопции Curl.

  • CURL_HTTP_VERSION_3 ( = int 30)

  • CURL_HTTP_VERSION_3ONLY ( = int 31)

$ch = curl_init("https://sergeymukhin.com/");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3);
curl_exec($ch);

Новые функции http_get_last_response_headers и http_clear_last_response_headers

В PHP 8.4 добавлены две новые функции, http_get_last_response_headers и http_clear_last_response_headers, которые можно использовать для получения и очистки HTTP-заголовков последнего HTTP ответа, которые могут заменить легендарную переменную $http_response_header.

Новая функция bcdivmod в расширении BCMath

Расширение BCMath в PHP 8.4 представляет новую функцию bcdivmod которая делит заданное число на заданный делитель и возвращает как частное, так и остаток, и это позволяет избежать необходимости вызывать функции bcdiv и bcmod по отдельности:

echo bcdivmod('42', '10');
// ["4", "2"]

echo bcdivmod("10", "10");
// ["1", "0"]

Новый метод DateTime createFromTimestamp

До PHP 8.4, чтобы создать экземпляр DateTime или DateTimeImmutable из временной метки UNIX, его нужно было создать с помощью createFromFormat:

$dt = DateTimeImmutable::createFromFormat('U', (string) 1703485481);
$dt->format('Y-m-d'); // "2023-12-25"


С PHP 8.4 классы DateTime и DateTimeImmutable в PHP 8.4 имеют новый метод createFromTimeStamp, позволяющий легко создать экземпляр из заданной временной метки UNIX в виде целого числа или значения с плавающей запятой.

$dt = DateTimeImmutable::createFromTimeStamp(1703485481);
$dt->format('Y-m-d'); //"2023-12-25"

Новые методы DateTime(Immutable)::get/setMicrosecond

Теперь классы DateTime и DateTimeImmutable в PHP 8.4 и более поздних версиях будут поддерживать методы getMicrosecond и setMicrosecond для получения и установки количества микросекунд для объектов DateTime/ DateTimeImmutable:

$date = new DateTimeImmutable(); 

$date->getMicrosecond(); // (int) 899561

$date = new DateTime(); 

$date->setMicrosecond(426286);
$date->getMicrosecond(); // (int) 426286

Новые функции mbstring: mb_trim, mb_ltrim, и mb_rtrim

В PHP 8.4 будут добавлены эквивалентные мультибайтные функции существующих trim, ltrim, и rtrim:

function mb_trim(string $string, string $characters = '...'): string

function mb_ltrim(string $string, string $characters = '...', ?string $encoding = null): string {}

function mb_rtrim(string $string, string $characters = '...', ?string $encoding = null): string {}

Новые функции mb_ucfirst и mb_lcfirst

В PHP есть функции ucfirst и lcfirst для изменения регистра первого символа в заданной строке. В PHP 8.4 расширение mbstring добавляет функции mb_ucfirst и mb_lcfirst в качестве многобайтовых безопасных альтернатив функциям ucfirst и lcfirst:

mb_ucfirst('test'); // Test
mb_ucfirst('тест'); // Тест

mb_lcfirst('Test'); // test
mb_lcfirst('Тест'); // тест

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

В PHP 8.4 добавлена ​​новая функция request_parse_body, которая предоставляет встроенную функциональность анализа запросов для других методов HTTP-запросов,таких как например PUT, DELETE и PATCH. Функция request_parse_body считывает все содержимое, которое доступно в потоке php://input и создает значения, которые можно использовать в переменных $_POST и $_FILES:

[$_POST, $_FILES] = request_parse_body();

Хуки свойств

Итак, наконец-то долгожданная обнова случилась и в PHP 8.4 у нас появятся полноценные свойства, с возможностью задавать хуки get и set (а в будущем и не только их):

class User 
{
    public string $name {
        set {
            if (strlen($value) === 0) {
                throw new ValueError("Name must be non-empty");
            }
            $this->name = $value;
        }
        get {
            return strtoupper($this->name);
        }
    }
 
    public function __construct(string $name) {
        $this->name = $name;
    }
}

Что примечательно, благодаря этому RFC так же можно асимметрично объявлять публичные свойства в интерфейсах. Класс реализации может предоставить свойство через обычное свойство или хуки:

interface I
{
    // Класс, реализующий интерфейс ДОЛЖЕН иметь публичное свойство,
    public string $readable { get; } 
    // Класс реализации ДОЛЖЕН иметь публичное свойство для записи,
    public string $writeable { set; } 
    // Класс реализации ДОЛЖЕН иметь свойство, которое является публичным и
    // доступно для чтения и записи.
    public string $both { get; set; }
}

Ассиметричная видимость свойств RFC

Одной из интересной особенностью PHP 8.4 является асимметричная видимость. Асимметричная видимость позволяет свойствам класса определять свою видимость (public, protected, или private) на основе контекста чтения или записи. Наиболее распространенным примером асимметричной видимости являются публичные свойства, которые можно изменять только изнутри класса. Такое свойство будет выглядеть следующим образом:

class BookModel
{
    public private(set) Author $author;
}

Поскольку публичные свойства, которые могут быть изменены только в частном контексте, являются наиболее распространенным вариантом использования асимметричной видимости, также доступна сокращенная запись:

class  BookModel
{
    private(set) Author $author; // то же самое, что и public private(set)
}

И конечно же, вы также можете сделать свойства доступными для записи только в пределах protected области:

class BookModel
{
    public protected(set) Author $author;
}

Синтаксис для свойств в конструкторе:

public function __construct(
    private(set) Author $author;
) {}

Lazy (ленивые) объекты RFC

В PHP 8.4 наконец-то добавлена ​​встроенная поддержка ленивых объектов - распространенного шаблона, используемого фреймворками для создания прокси-объектов, ленивая загрузка объектов в PHP уже используется в критически важных для бизнеса ситуациях. Например, Symfony использует их в своем компоненте внедрения зависимостей для предоставления ленивых сервисов, которые полностью инициализируются только при необходимости. Некоторые ORM делает свои сущности ленивыми, позволяя объектам гидратировать себя из базы данных только при обращении.

$initializer = static function (MyClass $proxy): MyClass {
    return new MyClass(123);
};
 
$reflector = new ReflectionClass(MyClass::class);

$object = $reflector->newLazyProxy($initializer);

Вывод feature_list в функции curl_version() расширения Curl

Функция curl_version в расширении Curl возвращает ассоциативный массив, содержащий информацию о версии и сборке Curl. Сюда входит версия Curl, имя и версия библиотеки SSL, версии Brotli и libz, список протоколов, поддерживаемых сборкой Curl, и битовая маска всех функций, поддерживаемых Curl. Битовая маска функций не позволяет интуитивно обнаружить и легко проверить, поддерживается ли конкретная функция (например, HTTP/2, HSTS и т. д.) в Curl.

В PHP 8.4 функция curl_version возвращает дополнительный ключ массива с именем feature_list, содержащий массив функций Curl и информацию о том, поддерживаются ли они:

curl_version();

//[
   "version_number" => 524801,
   "age" => 10,
   "features" => 1438631837,
    "feature_list" => [
      "AsynchDNS" => true,
      "CharConv" => false,
      "Debug" => false,
      // ...
      "HTTP2" => true,
      "HTTPS_PROXY" => true,
      "BROTLI" => true,
      "ALTSVC" => true,
      "HTTP3" => false,
      "ZSTD" => true,
      "HSTS" => true,
      // ...
    ],
   "ssl_version_number" => 0,
   "version" => "8.4.0",
   "host" => "x86_64-pc-linux-gnu",
   // ...
 ]

Новые режимы округления в функции round()

Функция round() округляет значение с плавающей точкой до ближайшего целого числа или десятичного значения указанной точности. Она поддерживает различные режимы округления, а PHP 8.4 добавляет четыре новых метода округления:

  • PHP_ROUND_CEILING: Округляет число до ближайшего целого числа, большего, чем число, превращая 1.1 и 1.5 в 2, а -1.1 и -1.5 в -1.

  • PHP_ROUND_FLOOR: Округляет число до ближайшего целого числа, меньшего числа, превращая 1.1 и 1.9 в -1 , а -1.9 и -1.1 в -2. Возвращаемое значение идентично возвращаемому значению функции floor.

  • PHP_ROUND_TOWARD_ZERO: Округляет число в сторону нуля, превращая 1.9 и 1.1 в 1, а -1.9 и -1.9 в -1.

  • PHP_ROUND_AWAY_FROM_ZERO: Округляет число от нуля, превращая 1.1 и 1.9 в 2, а -1,1 и -1.9 в -2 .

round(1.1, precision: 0, mode: PHP_ROUND_CEILING); // 2
round(1.1, precision: 1, mode: PHP_ROUND_FLOOR); // -1
round(1.9, precision: 0, mode: PHP_ROUND_TOWARD_ZERO); // 1
round(1.9,  precision: 0, mode: PHP_ROUND_AWAY_FROM_ZERO); // 2

Улучшение обратных вызовов в ext/dom и ext/xsl

В PHP 8.4 будет улучшена поддержка вызываемых типов XSLTProcessor::registerPHPFunctions() и DOMXPath::registerPhpFunctions() методов:

function my_callback(string $href): bool {
    return preg_match("/cat/", $href);
}
$xpath = new DOMXPath($doc);

// Это необходимо для разрешения имени php в выражении php:function ниже
$xpath->registerNamespace("php", "http://php.net/xpath");

// При этом функция "my_callback" регистрируется в XPath, так что может быть вызвана
$xpath->registerPhpFunctions("my_callback");

// При этом выбираются все теги <a>, где my_callback (содержимое их атрибута href) возвращает true.
$results = $xpath->evaluate("//a[php:function('my_callback', string(@href))]");
foreach ($results as $result) {
    echo "Found ", $result->textContent, "
";
}

/*
Found Jill
Found Kes
Found Minou
Found Tessa
*/ 

Изменения синтаксиса/функциональности

Exit/die переход с языковых конструкций на функции

Ключевое слово exit и его псевдоним die - это языковые конструкции, которые выводят сообщение и завершают текущий скрипт. В приложениях CLI exit/die может использоваться для завершения приложения с заданным кодом выхода. В PHP 8.4 exit/die будут являться функциями. Они будет иметь специальную обработку, позволяющую вызывать их без скобок для обеспечения обратной совместимости со старыми приложениями:

function exit(string|int $status = 0): never {}

exit; //валидно так же

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

В PHP 8.4 появилась возможность опускать дополнительные скобки при new выражении, т.е. вместо:

$request = (new Request())->withMethod('GET');

можно писать такой синтаксис:

$request = new Request()->withMethod('GET'); 

Хеширование паролей: алгоритмическая сложность Bcrypt по умолчанию изменена с 10 на 12

В PHP 8.4 параметр cost алгоритма PASSWORD_BCRYPT/PASSWORD_DEFAULT изменился с 10 на 12, чтобы сделать пароли более устойчивыми и сложными.

Это изменение по существу эквивалентно:

password_hash("some password", PASSWORD_BCRYPT, ["cost" => 12]);

Способ отключения JIT по умолчанию rfc

До PHP 8.4 JIT был отключен по умолчанию, используя значение по умолчанию opcache.jit_buffer_size=0 вместо opcache.jit=disable. Это фактически отключает JIT не потому, что jit=disable, а потому что размер буфера установлен равный 0.

В этом RFC предлагается изменить эти значения по умолчанию на выключенный jit и размер буфера на 64 мегабайт:

opcache.jit=disable
opcache.jit_buffer_size=64m

Тип констант PHP_ZTS и PHP_DEBUG изменен с int на bool

PHP_ZTS и PHP_DEBUG - две глобальные константы PHP, которые предоставляют информацию о текущей среде выполнения PHP.

  • PHP_ZTS: Указывает, является ли текущая сборка PHP потокобезопасной.

  • PHP_DEBUG: Указывает, является ли текущая сборка PHP отладочной сборкой.

До PHP 8.4 эти две константы содержали целочисленные значения: 0 когда отключено и 1 когда включено. Начиная с PHP 8.4 и более поздних версий, они изменились на логические значения .

if (PHP_ZTS === 1) {} //было
if (PHP_ZTS) {} //стало

Минимальная требуемая версия OpenSSL увеличена до 1.1.1

Это изменение увеличивает минимальную поддерживаемую версию библиотеки OpenSSL для расширения PHP OpenSSL до 1.1.1. За исключением серии RHEL/CentOS 7 , операционная система, скорее всего, предоставляет OpenSSL версии 1.1.1 или более поздней, и, таким образом, это изменение не окажет никакого влияния. RHEL/CentOS 7 прекращает свое существование на момент выпуска PHP 8.4.

Устаревшие функции

Неявные типы, допускающих NULL

В PHP наблюдалось странное поведение, при котором типизированная переменная со значением null по умолчанию автоматически становилась nullable. PHP 8.4 теперь не поддерживает неявно обнуляемые типы. Все объявления типов, имеющие значение по умолчанию null, но без объявления null в объявлении типа, выдают уведомление об устаревании:

function test(string $value = null) {}

//выдаст
//Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead

Рекомендуется привести к явному виду:

function test(?string $test = null) {}
//или
function test(string|null $test = null) {}

test('PHP'); // нормально
test(null); // нормально

Curl: CURLOPT_BINARYTRANSFER

Константа CURLOPT_BINARYTRANSFER, предоставляемая расширением Curl, устарела в PHP 8.4. Эта константа не имела никакого эффекта, начиная с PHP 5.1.2.

Константа E_STRICT устарела

Константа E_STRICT устарела в PHP 8.4. Использование константы в любом месте кода PHP теперь выдает уведомление об устаревании:

error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);

//Constant E_STRICT is deprecated

Вызов session_set_save_handler() с более чем 2 аргументами устарел RFC

session_set_save_handler('my_session_open', 'my_session_close', 'my_session_read', 'my_session_write', 'my_session_destroy', 'my_session_gc');

//Deprecated: Calling session_set_save_handler() with more than 2 arguments is deprecated in ... on line ...

Удалены функции и возможности

Pspell было перенесено из PHP Core в PECL

Расширение Pspell предоставляет из себя PHP функции проверки орфографии с помощью Pspell или Aspell. Зависимости этого расширения не получали никаких обновлений за последние несколько лет, в результате чего было принято решение расширение Pspell перенести из ядра PHP в расширение PECL в PHP 8.4.

IMAP было перенесено из PHP Core в PECL

Расширение IMAP в PHP обеспечивает функциональность для работы с почтовыми ящиками по протоколу IMAP. Базовая библиотека C, от которой зависит расширение, не получала никаких обновлений с 2018 года. Расширение IMAP также создает еще несколько проблем:

  • Отсутствие потокобезопасности. Сборки PHP-ZTS не могут собрать это расширение.

  • Отсутствие поддержки аутентификации XAUTH .

  • Ошибки в работе POP.

В PHP 8.4 расширение IMAP больше не является частью PHP Core и перешло в PECL, но рекомендуется перейти на альтернативные библиотеки, например Webklex/php-imap.

OCI8 и PDO-OCI были перенесены из PHP Core в PECL

Расширения oci8 и pdo_oci8 предоставляют функциональные возможности для использования баз данных Oracle в PHP. Эти расширения основаны на собственных библиотеках коммерческого поставщика Oracle. Эти расширения прошли длительный период накопления неисправленных ошибок и требуют значительных усилий для миграции их resource объектов в объекты классов. Учитывая зависимость этих расширений от сторонних проприетарных библиотек и необходимость усилий по их обслуживанию, расширения больше не являются частью ядра PHP и перешли на PECL как oci8 и pdo_oci.

Другое

Так же можно посмотреть черновик, связанный с функциями, которые должны быть объявлены устаревшими в PHP 8.4 и удалены в PHP 9.0:

  • DOMAttr::schemaTypeInfo и DOMElement::schemaTypeInfo

  • DOMImplementation::getFeature($feature, $version)

  • Constant DOM_PHP_ERR

  • mysqli_ping() и mysqli::ping()

  • Минимальная требуемая версия libcurl увеличена до 7.61.0

  • База данных символов Unicode в расширении mbstring обновлена ​​до версии 16

  • Недопустимые режимы округления функции round() вызывают исключения ValueError

Что думаешь?

Mihas28.10.2024

Работу с потоками и дженерики так и не завезли(

Сергей22.09.2024

Где-то пыха свернула не туда и стала превращаться в ES

zo0M30.06.2024

Очень информативно и без "воды", спасибо!

Илья23.06.2024

Очень свежий, оригинальный и необычный дизайн сайта!
Моё почтение!

Но я с ужасом увидел самую последнюю запись, что метод `mysqli::ping()` собираются признать устаревшим и удалить.

Призываю поддержать мой комментарий, или оставить свой, и не допустить этого.
https://github.com/php/php-src/pull/11945#issuecomment-2185148220

Qomi16.06.2024

Мне понравилось, спасибо :)

Человек09.02.2024

Замечательно, непосвящённому человеку почитать в сжатой форме на русском языке о нововведениях - да это же находка.

Категории
  • PHP 68
  • Заметки 18
  • Безопасность 4
  • Флуд 2
  • Nginx 2
  • ИТ новости 2
  • Видео 1
  • Docker 1
  • Roadmap 1
  • Архитектура 0

Хочешь поддержать сайт?

Делаем из мухи слона

sergeymukhin.com

персональный блог о веб-разработке от Сергея Мухина. Блог был основан в 2018 году, и собирался уделять основное внимание последним тенденциям, учебным пособиям, а также советам и рекомендациям, позволяющим начинающим девелоперам встать быстрее на правильную дорогу веб разработки, но что-то пошло не так 😃

Релизы PHP 8.4

Дата Релиз
4 Июля 2024 Альфа 1
18 Июля 2024 Альфа 2
1 Августа 2024 Альфа 3
13 Августа 2024 Feature freeze
15 Августа 2024 Бета 1
29 Августа 2024 Бета 2
12 Сентября 2024 Бета 3
26 Сентября 2024 RC 1
10 Октября 2024 RC 2
24 Октября 2024 RC 3
7 Ноября 2024 RC 4
21 Ноября 2024 GA

Что нового?