Класс PHP объявляется через class Name { ... } и содержит свойства (переменные) и методы (функции). new Name() создаёт по нему объект, а -> читает свойство или вызывает метод: $user->name, $user->greet().
Класс это чертёж, объект это одна вещь, собранная по нему. Из одного класса можно создать сколько угодно объектов, и у каждого свои значения свойств.
Свойства и методы
Свойство объявляется с ключевым словом видимости, необязательным типом и необязательным значением по умолчанию. Метод это функция внутри класса. Внутри метода $this это объект, для которого вызван метод, поэтому $this->balance читает баланс этого объекта.
Каждый объект хранит свой $balance: пополнение $a не трогает $b. Задавать свойства по одному после new утомительно; конструктор принимает начальные значения аргументами.
public, private и protected
Видимость определяет, кто может обращаться к свойству или вызывать метод:
| Ключевое слово | Доступно из |
|---|---|
public | откуда угодно |
protected | самого класса и классов, которые его наследуют |
private | только класса, который его объявил |
Сделать свойство private и открыть методы это способ, которым класс защищает собственные правила. Здесь баланс меняется только через deposit() и withdraw(), которые отклоняют неверные суммы:
Чтение закрытого свойства снаружи класса это не предупреждение, а Error:
Типизированные свойства и неинициализированные значения
Типизированное свойство без значения по умолчанию начинается как неинициализированное, а это не то же самое, что null. Чтение до первого присваивания выбрасывает Error. Либо задайте значение по умолчанию, либо присвойте его в конструкторе, либо сделайте свойство nullable через ?Type и = null.
Типы проверяются при присваивании. В режиме по умолчанию (нестрогом) $p->stock = '7' приводит числовую строку к 7, а $p->stock = 'many' выбрасывает TypeError.
readonly-свойства
Свойство readonly (PHP 8.1) можно записать один раз изнутри класса, и больше никогда. Это обычный способ строить объекты-значения, например денежные суммы или ID. В PHP 8.2 появился readonly class, который делает readonly все свойства.
У readonly-свойства должен быть тип, и значения по умолчанию у него быть не может. Если нужна изменённая копия, создайте новый объект (new Order('B-2002')), а не редактируйте старый.
Вывод объекта через __toString
echo $object работает, только если класс определяет __toString(). Метод возвращает строку, которую PHP использует всякий раз, когда объект трактуется как текст: в echo, при конкатенации строк, в "{$object}".
Без __toString echo $object выбрасывает Error ("Object of class Money could not be converted to string"). Для отладки print_r() и var_dump() работают с любым объектом и показывают и закрытые свойства; смотрите var_dump и print_r.
Присваивание объекта его не копирует
На этой ошибке спотыкается большинство тех, кто привык к массивам. Присваивание массива копирует его. Присваивание объекта копирует только дескриптор: обе переменные после этого указывают на один и тот же объект.
clone делает поверхностную копию: если свойство хранит другой объект, обе копии по-прежнему разделяют этот внутренний объект. === истинно только для одного и того же объекта, а == сравнивает значения свойств двух объектов одного класса. Передача объекта в функцию работает так же, как присваивание, поэтому функция может изменить полученный объект.
Часто задаваемые вопросы
Как создать объект класса в PHP?
Используйте new с именем класса: $user = new User();. Если у класса есть конструктор, передайте его аргументы в скобках, как в new User('Ada'). Затем вызывайте методы и читайте свойства через стрелку: $user->name, $user->greet().
Что означает $this в PHP?
$this это объект, для которого вызван текущий метод. Внутри $ada->greet() $this это $ada, поэтому $this->name читает имя Ada. $this существует только внутри нестатических методов.
Чем отличаются public, private и protected в PHP?
public члены доступны отовсюду, private только внутри класса, который их объявил, а protected в этом классе и его дочерних классах. Чтение закрытого свойства снаружи выбрасывает Error: Cannot access private property.
Передаются ли объекты в PHP по ссылке?
Переменная хранит дескриптор объекта, а не сам объект. $b = $a; копирует дескриптор, поэтому обе переменные указывают на один объект, и изменение через $b видно в $a. Используйте $b = clone $a;, чтобы получить независимую копию.
Что такое readonly-свойство в PHP?
Свойство, объявленное как public readonly string $id; (PHP 8.1+), можно задать один раз изнутри класса, и потом оно никогда не меняется. Повторная запись выбрасывает Error: Cannot modify readonly property.