Menu

Конструктор PHP: __construct и продвижение свойств

Конструктор PHP это метод __construct(), который выполняется автоматически, когда вы пишете new ClassName(...). Продвижение свойств в конструкторе, значения по умолчанию и именованные аргументы, проверка аргументов, parent::__construct() и как заменить несколько конструкторов статическими фабричными методами.

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

Конструктор PHP это метод с именем __construct(). PHP вызывает его автоматически, когда вы пишете new ClassName(...), а аргументы в скобках становятся его параметрами, поэтому объект начинает жизнь с уже заданными значениями.

Без конструктора вы создавали бы пустой объект и задавали каждое свойство потом, и ничто не помешало бы забыть одно из них. С конструктором new User() без аргументов вызывает ArgumentCountError.

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

Объявить свойство, указать его параметром и присвоить $this->name = $name значит повторить каждое имя трижды. Начиная с PHP 8.0 ключевое слово видимости перед параметром конструктора делает всё это разом:

Продвинутый параметр может быть и readonly (public readonly string $id), это самый короткий способ записать неизменяемый объект-значение. Продвинутые и обычные параметры можно смешивать, а в теле конструктора по-прежнему может быть код, который выполняется после присваивания продвинутых свойств.

Значения по умолчанию и именованные аргументы

Параметры конструктора принимают значения по умолчанию, как у любой функции. Параметры со значениями по умолчанию идут после обязательных. С именованными аргументами (PHP 8.0) вызывающий код может сразу указать нужную опцию, не повторяя все значения по умолчанию перед ней:

Запустите: в выводе есть HTML, поэтому вкладка Page показывает три отрисованные кнопки, а вкладка Output теги, которые напечатал PHP. Обратите внимание на скобки в (new Button('Save'))->render(): начиная с PHP 8.4 они необязательны, но PHP 8.3 они нужны.

Проверка аргументов в конструкторе

Конструктор не может вернуть false или код ошибки: всё, что он возвращает, игнорируется. Чтобы отклонить неверные данные, выбросьте исключение. Тогда объект вообще не создаётся, и остальная программа может доверять каждому полученному Temperature.

Перехват таких исключений подробнее описан на странице try catch.

Несколько конструкторов через статические фабричные методы

В PHP нет перегрузки конструкторов: один класс, один __construct. Когда объект можно собрать из разных входных данных (строка даты, массив, временная метка), добавьте именованные статические методы, которые готовят аргументы и вызывают new static(...). Если сделать конструктор private, всем придётся идти через фабрики.

new Color(1, 2, 3) снаружи класса теперь выбрасывает Error ("Call to private Color::__construct() from global scope"). Почему здесь используется new static, а не new self, объясняет страница о static.

Вызов конструктора родителя через parent::__construct

Когда дочерний класс определяет свой конструктор, конструктор родителя сам не выполняется. Вызовите его через parent::__construct(...), обычно первым, чтобы свойства родителя были заданы до того, как дочерний класс добавит свои:

Если у дочернего класса конструктора нет вовсе, PHP использует родительский, и new Truck('Volvo') передал бы аргументы прямо в Vehicle::__construct. Подробнее об этом в разделе о наследовании.

Забытый parent::__construct

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

Добавьте parent::__construct(); первой строкой в Post::__construct и запустите снова: код выведет дату. Связанный метод __destruct() выполняется, когда исчезает последняя ссылка на объект или завершается скрипт. В повседневном коде он нужен редко, потому что PHP сам закрывает файлы и освобождает память в конце каждого запроса.

Часто задаваемые вопросы

Что такое __construct в PHP?

__construct() это конструктор: метод, который PHP вызывает автоматически сразу после того, как new создал объект. Аргументы, переданные в new User('Ada', 36), попадают в __construct(string $name, int $age), который обычно сохраняет их в свойствах.

Что такое продвижение свойств в конструкторе PHP?

Начиная с PHP 8.0 ключевое слово видимости у параметра конструктора объявляет свойство и присваивает его за один шаг: public function __construct(private string $name) {} равносильно объявлению private string $name; и записи $this->name = $name; в теле.

Может ли у класса PHP быть несколько конструкторов?

Нет. В PHP нет перегрузки методов, поэтому у класса один __construct. Используйте необязательные параметры со значениями по умолчанию или добавьте статические фабричные методы вроде public static function fromArray(array $data): static, которые вызывают new static(...) с нужными аргументами.

Вызывается ли конструктор родителя в PHP автоматически?

Только когда у дочернего класса нет своего конструктора. Если дочерний класс определяет __construct, конструктор родителя не выполняется, пока вы сами не вызовете parent::__construct(...), обычно первой строкой.

Может ли конструктор PHP вернуть значение?

Нет. new всегда даёт объект, а то, что возвращает __construct, игнорируется. Чтобы сообщить о проблеме, выбросьте исключение из конструктора, например throw new InvalidArgumentException('Age must be positive').

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ