Introdução: por que SOLID é a base do código PHP de qualidade
Todo desenvolvedor PHP, mais cedo ou mais tarde, enfrenta a situação em que um pequeno projeto se transforma em "código espaguete". As classes ficam sobrecarregadas, mudanças em uma parte do sistema quebram outra, e os testes se tornam um pesadelo. É exatamente para resolver esses problemas que Robert Martin (Tio Bob) formulou os cinco princípios SOLID. Esses princípios não são teoria abstrata, mas ferramentas práticas que ajudam a criar código PHP flexível, sustentável e testável.
Neste artigo, vamos analisar cada princípio SOLID: da teoria aos exemplos reais em PHP 8.x. Você aprenderá como aplicá-los no desenvolvimento diário e quais antipadrões evitar.
1. Single Responsibility Principle (SRP) — princípio da responsabilidade única
Teoria
O princípio afirma: uma classe deve ter apenas um motivo para mudar. Isso significa que cada classe deve ser responsável por uma funcionalidade ou lógica de negócio específica.
Antipadrão (violação do SRP)
<?phpclass OrderProcessor { public function process(Order $order): void { // 1. Validação do pedido if (empty($order->getItems())) { throw new \\InvalidArgumentException('Order has no items'); } // 2. Salvamento no BD $db = new \\PDO('mysql:host=localhost;dbname=shop', 'user', 'pass'); $stmt = $db->prepare('INSERT INTO orders ...'); $stmt->execute([...]); // 3. Envio de email mail($order->getCustomerEmail(), 'Pedido confirmado', '...'); // 4. Registro de log file_put_contents('/var/log/orders.log', 'Order processed: '.$order->getId()); }}?>Aqui, a classe OrderProcessor faz demais: valida, trabalha com o BD, envia email, registra logs. A violação do SRP leva a que uma mudança na lógica de envio de email exija alteração na classe responsável pelo processamento de pedidos.
Refatoração com conformidade ao SRP
<?phpclass OrderValidator { public function validate(Order $order): void { if (empty($order->getItems())) { throw new \\InvalidArgumentException('Order has no items'); } }}
class OrderRepository { public function save(Order $order): void { // Lógica de salvamento no BD }}
class EmailNotifier { public function sendOrderConfirmation(Order $order): void { // Lógica de envio de email }}
class Logger { public function log(string $message): void { // Registro de log }}
class OrderProcessor { public function __construct( private OrderValidator $validator, private OrderRepository $repository, private EmailNotifier $notifier, private Logger $logger ) {} public function process(Order $order): void { $this->validator->validate($order); $this->repository->save($order); $this->notifier->sendOrderConfirmation($order); $this->logger->log('Order processed: '.$order->getId()); }}?>Agora cada classe tem uma única responsabilidade. A mudança na lógica de email não afeta o trabalho com o BD.
2. Open-Closed Principle (OCP) — princípio aberto/fechado
Teoria
As entidades de software devem estar abertas para extensão, mas fechadas para modificação. Em outras palavras, você deve ser capaz de adicionar nova funcionalidade sem alterar o código existente.
Antipadrão
<?phpclass PaymentProcessor { public function process(string $type, float $amount): void { if ($type === 'credit_card') { // Processamento de cartão de crédito } elseif ($type === 'paypal') { // Processamento do PayPal\