Работали ли вы с объектно-ориентированным программированием (ООП) в PHP?

Ответ

Да, ООП — это основа большинства современных PHP-проектов, над которыми я работал, будь то фреймворки вроде Laravel/Symfony или кастомные приложения.

Практический пример из проекта:

<?php

// Абстракция через интерфейс
interface NotificationSenderInterface {
    public function send(string $recipient, string $message): bool;
}

// Инкапсуляция и реализация
class EmailNotificationSender implements NotificationSenderInterface {
    private string $smtpHost;

    public function __construct(string $smtpHost) {
        $this->smtpHost = $smtpHost; // Данные скрыты (инкапсуляция)
    }

    public function send(string $recipient, string $message): bool {
        // Логика отправки email
        return true;
    }
}

// Наследование и полиморфизм
abstract class AbstractLogger {
    abstract public function log(string $level, string $message): void;

    public function info(string $message): void {
        $this->log('INFO', $message); // Общий шаблон
    }
}

class FileLogger extends AbstractLogger {
    public function log(string $level, string $message): void {
        file_put_contents('app.log', "[$level] $messagen", FILE_APPEND);
    }
}

// Использование (полиморфизм)
$notifier = new EmailNotificationSender('smtp.example.com');
$logger = new FileLogger();

$logger->info('Notification service initialized.');
$notifier->send('user@example.com', 'Welcome!');

Из реального опыта:

  • Активно применял трейты (trait) для горизонтального повторного использования кода, например, для добавления поведения SoftDeletes или Timestampable в модели.
  • Использовал магические методы, такие как __get()/__set() для динамических свойств или __invoke() для создания callable-объектов.
  • Следование принципам SOLID (особенно Dependency Injection и Interface Segregation) было ключевым для создания поддерживаемых и тестируемых сервисов в Symfony.

Ответ 18+ 🔞

Да ты посмотри, какой тут разговор про ООП подняли! Ну, ебать мои старые костыли, конечно, это основа основ. Без этого нихуя не построишь ни в Laravel, ни в каком-нибудь своём кастомном приложении, которое потом полгода разгребать.

Вот тебе пример, как оно на практике выглядит, прямо из проекта:

<?php

// Сначала интерфейс — договор, что все, кто его использует, будут уметь одно и то же
interface NotificationSenderInterface {
    public function send(string $recipient, string $message): bool;
}

// А вот конкретная реализация. Всё спрятано внутри, это и есть инкапсуляция
class EmailNotificationSender implements NotificationSenderInterface {
    private string $smtpHost; // Смотри, приватное свойство — снаружи него не видно, хитрая жопа

    public function __construct(string $smtpHost) {
        $this->smtpHost = $smtpHost;
    }

    public function send(string $recipient, string $message): bool {
        // Тут бывает логика отправки, но сейчас просто заглушка
        return true;
    }
}

// А вот наследование, ёпта. Абстрактный класс — как чертёж общего поведения
abstract class AbstractLogger {
    abstract public function log(string $level, string $message): void; // Заставляем детей реализовать

    public function info(string $message): void {
        $this->log('INFO', $message); // А это общий шаблон, который уже готов
    }
}

// И вот наследник, который делает всё по-своему
class FileLogger extends AbstractLogger {
    public function log(string $level, string $message): void {
        file_put_contents('app.log', "[$level] $messagen", FILE_APPEND);
    }
}

// А вот и полиморфизм, красота! Работаем с объектами через их общие интерфейсы
$notifier = new EmailNotificationSender('smtp.example.com');
$logger = new FileLogger();

$logger->info('Notification service initialized.');
$notifier->send('user@example.com', 'Welcome!');

А из реального опыта, так это вообще песня:

  • Трейты — это просто волшебство, ебать колотить. Чтобы не копипастить один и тот же код в десять разных классов, выносишь его в трейт, типа SoftDeletes или Timestampable, и подключаешь куда надо. Удобно, как хуй с горы скатиться.
  • Магические методы — это отдельная история. __get() с __set() — когда нужно сделать динамические свойства, а __invoke() — чтобы объект можно было вызывать как функцию. Сильная штука, но главное не переборщить, а то получится пиздопроебибна, в которой потом сам черт ногу сломит.
  • Ну и SOLID, конечно. Особенно Dependency Injection и разделение интерфейсов. Когда каждый сервис зависит от абстракции, а не от конкретной реализации, тестировать и менять код — одно удовольствие. А иначе потом подозрение ебать чувствуешь, глядя на спагетти-код, который написал полгода назад.