ООП в PHP похоже на Java и C#, но со своими особенностями: трейты, позднее статическое связывание, магические методы. На собесе любят self против static, трейты против интерфейсов и clone.
Классы
final class Order
{
public function __construct(
private readonly int $id,
private OrderStatus $status = OrderStatus::New,
) {}
public function pay(): void
{
if ($this->status !== OrderStatus::New) {
throw new DomainException('Заказ уже оплачен или отменён');
}
$this->status = OrderStatus::Paid;
}
}
Продвижение свойств в конструкторе (8.0), readonly (8.1), видимость public, protected, private. final запрещает наследование класса или переопределение метода (и константы с 8.1).
Абстрактный класс и интерфейс
- Интерфейс: только сигнатуры публичных методов и константы, класс реализует сколько угодно интерфейсов, интерфейс является типом.
- Абстрактный класс: состояние, конструктор, реализованные и абстрактные методы, наследуется один.
Трейты
trait HasSlug
{
abstract protected function title(): string;
public function slug(): string { return strtolower(str_replace(' ', '-', $this->title())); }
}
class Post { use HasSlug; protected function title(): string { return $this->title; } }
Трейт копирует код в класс. Он не тип (instanceof не работает). Конфликты имён решают insteadof и as. Приоритет: метод класса > метод трейта > унаследованный метод. Трейты хороши для мелкой сквозной функциональности (SoftDeletes), но прячут зависимости, поэтому бизнес-логику лучше выносить в сервисы и внедрять.
self, static, parent
class Model {
public static function create(): static { return new static(); }
}
class User extends Model {}
User::create(); // объект User, а с new self() был бы Model
self это класс, где написан код, static это класс, через который вызвали (позднее статическое связывание), parent родитель.
Магические методы
__get, __set, __isset, __unset (недоступные свойства), __call, __callStatic (недоступные методы), __toString, __invoke, __clone, __serialize/__unserialize. На них построены модели Eloquent и фасады Laravel. Цена: анализатор и IDE хуже понимают код.
Сравнение и клонирование
==для объектов: тот же класс и равные свойства,===: тот же экземпляр.- Присваивание и передача копируют дескриптор:
$b = $aэто тот же объект. cloneповерхностный: вложенные объекты общие. Глубокую копию делают в__clone().
SOLID в PHP
Тонкие контроллеры, логика в сервисах, зависимости через конструктор от интерфейсов, реализацию подставляет контейнер Laravel или Symfony. Интерфейс заводят там, где есть вариативность или граница с внешней системой, а не для каждого класса.
Частые ошибки
new self()в базовом классе фабрики.- Ожидание глубокой копии от
clone. - Логика в трейтах вместо композиции.
- Публичные свойства без инвариантов вместо методов предметной области.
Что спросят на собесе
- Чем трейт отличается от интерфейса и абстрактного класса?
selfпротивstatic: что такое позднее статическое связывание?- Как работает
cloneи как сделать глубокую копию? - Какие магические методы вы знаете и где они используются?
- Расскажите SOLID на примере PHP-кода.