O Composer é uma ferramenta essencial para o desenvolvimento moderno em PHP. Ele gerencia as dependências do seu projeto, permitindo que você declare quais bibliotecas seu projeto precisa e ele cuida da instalação, atualização e autoload dessas bibliotecas. Nesta aula, vamos explorar desde os conceitos básicos até a configuração do autoload, com exemplos práticos.

Imagine que você está construindo uma aplicação que precisa de um pacote para gerar PDFs, outro para envio de e-mails e um terceiro para manipulação de imagens. Sem o Composer, você teria que baixar cada biblioteca manualmente, configurar o autoload de cada uma e lidar com as dependências entre elas. Com o Composer, basta declarar os pacotes no arquivo composer.json e ele resolve tudo para você. Vamos ver como isso funciona na prática.

O que é

O Composer é um gerenciador de dependências para PHP, inspirado em ferramentas como o npm (Node.js) e o Bundler (Ruby). Ele foi criado por Nils Adermann e Jordi Boggiano e lançado em 2012. O Composer permite que você declare as bibliotecas das quais seu projeto depende, e ele gerencia a instalação e a atualização dessas bibliotecas, além de gerar o autoload para que você possa usar as classes sem se preocupar com require manual.

O Composer funciona através de um arquivo chamado composer.json, que fica na raiz do projeto. Nesse arquivo, você especifica as dependências, a versão do PHP, o autoload e outras configurações. O Composer também gera um arquivo composer.lock, que registra as versões exatas das dependências instaladas, garantindo que todos os desenvolvedores do projeto usem as mesmas versões. Além disso, ele cria uma pasta vendor onde os pacotes são instalados.

composer.json

O arquivo composer.json é o coração do Composer. Ele é escrito em JSON e contém as informações sobre o projeto e suas dependências. Vamos criar um exemplo básico:

{
    "name": "meu-projeto/meu-app",
    "description": "Um exemplo de aplicação PHP",
    "type": "project",
    "require": {
        "php": ">=8.0",
        "monolog/monolog": "^2.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

O campo name é o nome do seu pacote, geralmente no formato vendor/package. O campo description é opcional, mas recomendado. O campo type define se é um projeto ou uma biblioteca. O campo require lista as dependências, com as restrições de versão. No exemplo, exigimos PHP 8.0 ou superior e o Monolog na versão 2.x. O campo autoload configura o autoload PSR-4, que veremos mais adiante.

Além desses, existem outros campos como require-dev para dependências de desenvolvimento, scripts para executar comandos, e repositories para fontes alternativas. O Composer também suporta a definição de minimum-stability para permitir versões instáveis. É importante entender que o composer.json é versionado junto com o projeto, mas o composer.lock também deve ser versionado para garantir consistência.

Instalando dependências

Para instalar as dependências declaradas no composer.json, você executa o comando composer install. Esse comando lê o composer.json e o composer.lock (se existir) e instala as versões exatas das dependências. Se não houver composer.lock, ele resolve as versões de acordo com as restrições e cria o arquivo composer.lock.

Para adicionar uma nova dependência, você pode usar o comando composer require nome/pacote. Por exemplo:

composer require guzzlehttp/guzzle

Isso atualiza o composer.json e instala o pacote automaticamente. Para atualizar todas as dependências para as versões mais recentes dentro das restrições, use composer update. Para remover uma dependência, use composer remove nome/pacote.

O Composer também permite instalar dependências de desenvolvimento com o composer require --dev nome/pacote. Essas dependências são usadas apenas em ambiente de desenvolvimento, como ferramentas de teste ou análise de código.

Autoload via Composer

Um dos maiores benefícios do Composer é o autoload. Ele gera um arquivo vendor/autoload.php que você inclui no início do seu projeto, e a partir daí todas as classes das dependências são carregadas automaticamente quando você as usa. Você não precisa mais escrever require para cada classe.

Além de carregar as classes das dependências, o Composer também pode carregar as suas próprias classes usando o padrão PSR-4. No composer.json, você define um namespace e o diretório correspondente. Por exemplo, se você tem o namespace App e o diretório src, a classe App\Controller\UserController estará em src/Controller/UserController.php. O Composer registra um autoloader que resolve as classes conforme a convenção.

Para usar o autoload, basta incluir o arquivo vendor/autoload.php no início do seu script:

require __DIR__ . '/vendor/autoload.php';

Depois disso, você pode instanciar qualquer classe sem se preocupar com a inclusão manual. Além do PSR-4, o Composer também suporta PSR-0, classmap e arquivos. O PSR-4 é o mais recomendado por ser mais eficiente e moderno.

Boas práticas

Ao usar o Composer, é importante seguir algumas boas práticas. Primeiro, sempre versione o composer.lock para que todos os desenvolvedores usem as mesmas versões das dependências. Segundo, evite commitar a pasta vendor; ela deve ser ignorada no seu controle de versão. Terceiro, use restrições de versão adequadas: ^ permite atualizações dentro da mesma versão major, ~ permite dentro da mesma versão minor. Quarto, organize seu código em namespaces e use PSR-4 para o autoload. Quinto, execute composer update com cuidado, pois pode trazer mudanças que quebram o código.

Referências

Exercícios

  1. Qual é a finalidade do arquivo composer.lock e por que ele deve ser versionado?

    ✓ Resposta: O composer.lock registra as versões exatas das dependências instaladas. Ele deve ser versionado para garantir que todos os desenvolvedores e ambientes de produção usem exatamente as mesmas versões, evitando inconsistências.
  2. Explique a diferença entre composer install e composer update.

    ✓ Resposta: composer install instala as dependências conforme o composer.lock (se existir), garantindo as versões exatas. composer update atualiza as dependências para as versões mais recentes permitidas pelas restrições do composer.json e gera um novo composer.lock.
  3. Crie um composer.json para um projeto que requer a biblioteca phpunit/phpunit na versão 9.5 (ou superior, mas menor que 10) e configura o autoload PSR-4 para o namespace MeuApp apontando para o diretório src.

    ✓ Resposta:
    {
        "name": "meuapp/meuapp",
        "require": {
            "phpunit/phpunit": "^9.5"
        },
        "autoload": {
            "psr-4": {
                "MeuApp\\": "src/"
            }
        }
    }
  4. Como você carregaria o autoload do Composer em um script PHP? Escreva o código necessário.

    ✓ Resposta:
    require __DIR__ . '/vendor/autoload.php';
  5. Qual é a diferença entre as dependências listadas em require e require-dev? Dê um exemplo de cada.

    ✓ Resposta: As dependências em require são necessárias para o funcionamento da aplicação em produção, como um framework ou biblioteca de banco de dados. As dependências em require-dev são usadas apenas em desenvolvimento, como ferramentas de teste (PHPUnit) ou análise de código (PHPStan). Exemplo: require pode ter monolog/monolog, e require-dev pode ter phpunit/phpunit.