Sobes.tech
Middle

O que é injeção de dependências e como é aplicada no desenvolvimento em PHP?

sobes.tech IA

Resposta da IA

A injeção de dependências (DI) é um padrão de projeto que permite a um objeto obter dependências de outro objeto ou framework, em vez de as criar por si próprio. Isto facilita a gestão das dependências das classes e torna o código mais flexível, testável e sustentável.

Em PHP, a DI é aplicada para:

  • Reduzir o acoplamento: As classes não estão fortemente ligadas a implementações específicas das suas dependências.
  • Simplificar os testes unitários: É fácil substituir dependências reais por objetos simulados para testes.
  • Aumentar a flexibilidade e extensibilidade: É fácil alterar ou substituir implementações de dependências sem modificar a classe que as utiliza.

Existem três abordagens principais para a injeção de dependências:

  1. Injeção através do construtor (Constructor Injection): As dependências são passadas como argumentos ao construtor da classe. É o método preferido, pois garante a disponibilidade das dependências necessárias ao criar o objeto.

    <?php
    class DatabaseConnection
    {
        // Detalhes de conexão à base de dados
    }
    
    class UserRepository
    {
        private DatabaseConnection $db;
    
        public function __construct(DatabaseConnection $db)
        {
            $this->db = $db;
        }
    
        // Métodos do repositório
    }
    
    // Criação do objeto com injeção de dependência
    $db = new DatabaseConnection();
    $userRepository = new UserRepository($db);
    
  2. Injeção através do setter (Setter Injection): As dependências são injetadas através de métodos públicos setters. Permite que as dependências sejam opcionais.

    <?php
    class Logger
    {
        // Registo
    }
    
    class UserService
    {
        private ?Logger $logger = null; // Dependência opcional
    
        public function setLogger(Logger $logger): void
        {
            $this->logger = $logger;
        }
    
        public function doSomething(): void
        {
            if ($this->logger) {
                $this->logger->log("A fazer algo...");
            }
            // Lógica principal
        }
    }
    
    // Criação do objeto e injeção opcional de dependência
    $userService = new UserService();
    $logger = new Logger();
    $userService->setLogger($logger);
    
  3. Injeção através da interface (Interface Injection): A classe que necessita da dependência implementa uma interface que define um método para estabelecer essa dependência. É menos comum em PHP em comparação com os outros dois.

Em aplicações PHP reais, muitas vezes são utilizados contentores de injeção de dependências (Dependency Injection Containers). São bibliotecas ou frameworks que automatizam o processo de criação de objetos e suas dependências. O contentor pode analisar as dependências de uma classe e criar e injetar automaticamente os objetos necessários.

Exemplos populares de contentores DI para PHP:

  • PHP-DI
  • Symfony\DependencyInjection
  • Laravel Service Container (incluído no Laravel)

Utilização do contentor DI:

<?php
// Exemplo com um pseudo-contentor
// Normalmente, o contentor é configurado através de ficheiros de configuração (YAML, arrays PHP, etc.)

// Configuração do contentor (simplificada)
$container->set(DatabaseConnection::class, function() {
    return new DatabaseConnection(); // Criação de uma instância
});

$container->set(UserRepository::class, function($container) {
    // Injeção de dependência DatabaseConnection ao criar UserRepository
    return new UserRepository($container->get(DatabaseConnection::class));
});

// Obter um objeto do contentor: o contentor criará e injetará automaticamente as dependências
$userRepository = $container->get(UserRepository::class);

Resumindo, a injeção de dependências em PHP é um padrão chave para construir código flexível, testável e sustentável, especialmente em grandes projetos e ao usar frameworks.