В этом релизе появятся хуки свойств, поддержка HTML5, а также возможность цепочки методов без дополнительных скобок — это действительно важное изменение!

#Хуки свойств (Property Hooks) RFC

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

class BookViewModel
{
    public function __construct(
        private array $authors,
    ) {}
    
    public string $credits {
        get {
            return implode(', ', array_map(
                fn (Author $author) => $author->name, 
                $this->authors,
            ));
        }
    }
    
    public Author $mainAuthor {
        set (Author $mainAuthor) {
            $this->authors[] = $mainAuthor;
            $this->mainAuthor = $mainAuthor;
        }
        
        get => $this->mainAuthor;
    }
}

Цель хуков свойств заключается в том, чтобы избавиться от большого количества геттеров и сеттеров, позволяя каждому свойству определять свои собственные хуки для получения и установки значения. Хуки являются необязательными, и вы можете добавлять только один из них для конкретного свойства. Например, свойство с одним лишь хуком get является виртуальным свойством.

Есть еще много чего рассказать о хуках свойств, и я планирую написать отдельный пост об этом в ближайшее время, так что обязательно подпишитесь, если хотите узнать больше. Одна последняя вещь, которую я хотел бы отметить — возможно, то, что меня больше всего радует: хуки свойств можно определять в интерфейсах!

interface HasAuthors
{
    public string $credits { get; }
    public Author $mainAuthor { get; set; }
}

#Создание объектов без скобок (new without parentheses) RFC

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

$name = (new ReflectionClass($objectOrClass))->getShortName();

Теперь можно делать так:

$name = new ReflectionClass($objectOrClass)->getShortName()

Я не знаю как вы, но я пишу много такого кода, и поэтому очень рад, что наконец-то мы избавляемся от этих лишних скобок. Это работает не только для методов, кстати. Вы также можете использовать цепочки для свойств, статических методов, констант — чего угодно. Подробнее об этой новой функции можно прочитать в специальном посте .

#Асимметричная видимость (Asymmetric Visibility) RFC

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

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

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

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

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

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

И, естественно, этот синтаксис работает и для продвигаемых свойств:

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

#Функция array_find() RFC

В PHP 8.4 добавлена довольно простая новая функция, о которой многие разработчики могли задаться вопросом: «Подождите, разве этого еще не было?». Многие привыкли к сторонним коллекциям, хотя я думаю, что наличие array_find() нативно в PHP — это довольно удобно.

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

$firstMatch = array_find(
    $posts, 
    function (Post $post) {
        return strlen($post->title) > 5; 
    }
);

Также есть несколько вариаций этой функции: array_find_key(), array_any() и array_all(). Подробнее о них можно прочитать здесь .

#Устаревание неявных nullable типов

Раньше PHP имел странное поведение, когда типизированная переменная с дефолтным значением null автоматически становилась nullable:

function save(Book $book = null) {}
// Устарело: Неявное указание параметра $book как nullable устарело,
// необходимо явно указывать nullable тип

Это поведение теперь устарело и будет удалено в PHP 9. Решение — явно указать nullable:

function save(?Book $book = null) {}

#Новая поддержка HTML5 RFC

PHP 8.4 добавляет класс \Dom\HTMLDocument, который способен правильно парсить HTML5 код. Старый класс \DOMDocument все еще доступен для обратной совместимости.

$doc = \Dom\HTMLDocument::createFromString($contents);

Подробнее о новом HTML5 парсере можно прочитать здесь .

#Изменения JIT RFC

PHP 8.4 меняет способ включения JIT. Раньше вам нужно было установить opcache.jit_buffer_size в 0, чтобы отключить JIT, но теперь вы можете отключить его следующим образом:

opcache.jit=disable
opcache.jit_buffer_size=64m

Единственный случай, когда пользователи могут быть затронуты этим изменением, — если они указали opcache.jit_buffer_size, но не указали opcache.jit. В этом случае вам нужно будет добавить opcache.jit=tracing, чтобы снова включить JIT.

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

#Ленивые объекты (Lazy Objects) RFC

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

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

#exit и die как функции RFC

В PHP exit (и его псевдоним die) — это довольно странные вещи: их можно использовать как ключевые слова (exit;), но также и как функции (exit(0);). Однако вариант функции на самом деле не был полноценной функцией, а скорее чем-то, что ведет себя как функция, но не полностью:

  • не поддерживал именованные аргументы;
  • не мог передаваться как callable;
  • игнорировал strict_types;
  • не следовал обычным правилам преобразования типов.

С PHP 8.4 exit() и die() теперь правильно рассматриваются как функции, и все вышеупомянутые проблемы исправлены. Обратите внимание, что вариант с ключевым словом без скобок, конечно, продолжает работать так же.

#Объектный API для BCMath RFC

Раньше bcmath поддерживал только функциональный API. С PHP 8.4 вы можете использовать объектно-ориентированный API. Особенно круто в этой функции то, что эти объекты Number поддерживают перегрузку операторов, и вы можете использовать их непосредственно в вычислениях!

use BCMath\Number;

$num = new Number('1');
$num2 = new Number('2');
$result = $num + $num2;

$result->value; // '3'

#Атрибут #[Deprecated] RFC

Теперь в PHP есть встроенный атрибут, который можно использовать для пометки методов, функций и классов как устаревших. Раньше вы могли использовать docblock вроде /** @deprecated */, но PHP ничего с этим не делал. Хотя статические анализаторы и IDE могли интерпретировать эти docblocks, вам нужны были внешние инструменты, чтобы убедиться, что все устаревшие элементы были обнаружены.

Теперь пакеты и фреймворки могут полагаться на встроенный атрибут #[Deprecated], который также поддерживает добавление метаданных:

#[Deprecated("используйте newFunction() вместо", since: "tempest/framework:1.1")]
function oldFunction() {
    // …
}

#добавления

  • Новая функция request_parse_body(), которая позволяет парсить RFC1867 (multipart) запросы в HTTP-запросах, отличных от POST. Читать подробнее
  • Новые статические конструкторы для создания объектов DateTime и DateTimeImmutable из временной метки: DateTime::createFromTimestamp($timestamp) и DateTimeImmutable::createFromTimestamp($timestamp)
  • Две новые функции, связанные с микросекундами в объектах DateTime и DateTimeImmutable: DateTime::getMicrosecond() и DateTimeImmutable::setMicrosecond($microsecond)
  • Теперь есть поддержка драйвер-специфичных подклассов PDO. Читать подробнее
  • Новая поддержка драйвер-специфичных SQL-парсеров. Читать подробнее

#Обратно несовместимые изменения

Полный список изменений здесь

PHP 8.4 приносит множество инноваций, которые значительно упрощают разработку и повышают производительность. От хуков свойств до улучшений JIT — каждое изменение направлено на то, чтобы сделать код более чистым, безопасным и эффективным. Если вы хотите быть в курсе последних тенденций в мире PHP, обязательно изучите все новые функции PHP 8.4 и внедрите их в свои проекты. Это не только улучшит качество вашего кода, но и позволит вам оставаться конкурентоспособным на рынке разработки.

Не забудьте подписаться на наш блог, чтобы получать уведомления о новых статьях и обновлениях в мире программирования!