Поиск по сайту:

Продвижение свойства конструктора в PHP 8


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

Традиционный класс

Продвижение свойств конструктора (далее CPP) наиболее полезно в контексте объектов-значений. Обычно это простые классы, описывающие структуру данных. Вот как это может выглядеть в PHP 7.4:

class BlogPost {
 
    protected string $Title;
 
    protected string $Content;
 
    protected DateTimeImmutable $PostedDate;
 
 
    public function __construct(
        string $Title,
        string $Content,
        DateTimeImmutable $PostedDate) {
 
        $this -> Title = $Title;
        $this -> Content = $Content;
        $this -> PostedDate = $PostedDate;
    }
 
}

Мы создали достаточно длинный класс, несмотря на то, что в нем всего три свойства! Каждое имя свойства встречается четыре раза, а подсказки записываются дважды. Если вам нужно изменить одно из свойств или добавить другое, вам придется коснуться трех строк кода.

Добавление продвижения свойств конструктора

Вот тот же пример, переписанный для использования CPP в PHP 8:

class BlogPost {
    public function __construct(
        protected string $Title,
        protected string $Content,
        protected DateTimeImmutable $PostedDate) {}
}

Используя CPP, мы резко сократили размер нашего класса. Вам нужно будет добавить или изменить только одну строку кода при работе со свойствами этого класса.

Пристальный взгляд

CPP объединяет определение свойства со списком параметров конструктора. Чтобы создать продвигаемое свойство, добавьте к его имени модификатор видимости класса — public, protected или private.

После повышения свойство ведет себя как любое другое свойство класса. Вы можете получить к нему доступ внутри класса с помощью $this -> Property или извне (если это свойство public). Внутри PHP просто преобразует компактный синтаксис в гораздо более длинную версию, поддерживаемую PHP 7.

Вам не нужно использовать подсказки типов с продвигаемыми свойствами — допустимо написать, например, protected $Title. Вы можете установить значения по умолчанию, используя тот же синтаксис, что и для обычного параметра конструктора (защищенная строка $Title=\Example Post\).

Использование с телом конструктора

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

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

public function __construct(protected string $Title) {
    if (!$this -> Title) {
        throw new InvalidArgumentException("Title cannot be empty.");
    }
    // OR
    if (!$Title) {
        throw new InvalidArgumentException("Title cannot be empty.");
    }
}

Какой бы подход вы ни выбрали, переменную или свойство, вы будете работать с одним и тем же значением. PHP просто скрывает строку $this -> Title=$Title, которую вы обычно пишете вручную.

Объединение с обычными свойствами и параметрами

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

class BlogPost {
    public ?DateTimeImmutable $PostedDate = null;
 
    public function __construct(public string $Title, bool $isPosted=true) {
        if ($isPosted) $this -> PostedDate = new DateTimeImmutable();
    }
}

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

Использовать с атрибутами

Одной из других новых функций PHP 8 были атрибуты. Это позволяет вам аннотировать дополнительные метаданные относительно сущностей в вашей кодовой базе.

Атрибуты полностью поддерживаются продвигаемыми свойствами. Поскольку неясно, применяется ли атрибут к определению свойства или к параметру метода, PHP применит его к обоим.

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

Отражение

Продвигаемые свойства — и аргументы конструктора, которые продвигают свойство — ведут себя интуитивно при самоанализе через API-интерфейсы Reflection. Отражение просматривает продвинутые свойства в их состоянии после трансляции, поэтому они выглядят идентичными явно объявленному свойству.

Оба класса ReflectionProperty и ReflectionParameter имеют новые методы isPromoted(), позволяющие проверить, связаны ли они с CPP. Как правило, это не нужно учитывать, если только вы не пишете инструмент, который хочет воспроизвести точную исходную структуру.

Возможные ошибки

Вы не можете объявлять повторяющиеся имена классов и продвинутых свойств. Следующий пример приведет к ошибке времени выполнения:

class BlogPost {
    public string $Title;
 
    public function __construct(public string $Title) {}
}

Это связано с тем, что PHP не делает ничего особенного с продвинутыми определениями свойств. Он просто преобразует ваш краткий исходный код в стиль PHP 7.4. Это приведет к появлению двух строк public string $Title, что всегда было запрещено.

Есть и другие случаи, когда CPP может привести к ошибке. Продвинутые свойства запрещены в абстрактных классах, хотя их можно использовать в трейтах. Вы не можете использовать с ними тип callable, потому что он не поддерживается для определений свойств. Наконец, нет поддержки вариативных параметров (например, public string ...$strings), потому что в конечном итоге свойство будет массивом из string. экземпляры, а не сама строка.

Заключение

Повышение свойств конструктора значительно ускоряет создание новых объектов-значений в кодовой базе. Он может сократить количество строк до двух третей! CPP также помогает вам СУШИТЬ (не повторяйте себя) ваш код, избегая неприглядного повторения подсказок и имен свойств, которые требуются в PHP 7.4.

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




Все права защищены. © Linux-Console.net • 2019-2024