Composer na prática: instalando, atualizando e lockfile

1. Introdução ao Composer e seu papel no ecossistema PHP

O Composer é, sem dúvida, uma das ferramentas mais importantes para o desenvolvimento PHP moderno. Antes dele, gerenciar bibliotecas de terceiros era um processo manual e propenso a erros: os desenvolvedores baixavam arquivos, colavam em pastas e configuravam includes manualmente. O Composer mudou esse cenário ao introduzir um gerenciador de dependências robusto, similar ao que npm representa para JavaScript ou Bundler para Ruby.

Com o Composer, você declara as bibliotecas que seu projeto precisa em um arquivo chamado composer.json, e ele se encarrega de baixar as versões corretas, resolver dependências transitivas e configurar o autoloading. O fluxo de trabalho básico envolve três elementos principais:

  • composer.json: arquivo de configuração que define as dependências e suas restrições de versão
  • composer.lock: snapshot exato das versões instaladas (fundamental para reprodutibilidade)
  • pasta vendor/: diretório onde as dependências são baixadas e o autoloading é gerado

2. Instalação do Composer e configuração inicial

A instalação do Composer pode ser feita globalmente no sistema. No Linux e macOS, o método mais comum é via terminal:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer

No Windows, o instalador gráfico disponível em getcomposer.org é a opção mais prática. Após a instalação, verifique com:

composer --version

Para iniciar um projeto, você pode criar o composer.json manualmente ou usar o comando interativo:

composer init

Este comando faz perguntas sobre o projeto (nome, descrição, autor, etc.) e gera um arquivo inicial. A estrutura básica do composer.json contém a seção require para dependências de produção e require-dev para ferramentas de desenvolvimento:

{
    "name": "meu/projeto",
    "require": {
        "monolog/monolog": "^2.0",
        "guzzlehttp/guzzle": "~7.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.5"
    }
}

Os operadores de versão merecem atenção:
- ^2.0: permite atualizações até a próxima versão major (2.x.x, mas não 3.0.0)
- ~7.0: permite apenas patches (7.0.x)
- *: qualquer versão (não recomendado para produção)

3. Instalando dependências com composer install

Quando você executa composer install, o Composer primeiro verifica se existe um arquivo composer.lock. Se existir, ele lê as versões exatas de lá e as instala. Se não existir, ele resolve as dependências a partir do composer.json e gera o lockfile.

composer install

Para instalar apenas dependências de produção (ignorando require-dev), use a flag --no-dev:

composer install --no-dev --optimize-autoloader

Isso é especialmente útil em ambientes de produção, onde ferramentas de teste não são necessárias. Ao final da instalação, a pasta vendor/ conterá todas as bibliotecas baixadas, e o arquivo vendor/autoload.php será gerado automaticamente, permitindo o carregamento automático das classes:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('meu_app');
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));
$log->warning('Exemplo de log com Monolog');

4. O lockfile (composer.lock) e sua importância

O composer.lock é um arquivo JSON que registra as versões exatas de todas as dependências instaladas, incluindo as dependências transitivas. Ele funciona como um "instantâneo" do estado do projeto em um determinado momento.

A principal razão para versionar o composer.lock no Git é garantir reprodutibilidade. Imagine que sua equipe tem 5 desenvolvedores e um servidor de CI/CD. Sem o lockfile, cada execução de composer install poderia resolver versões ligeiramente diferentes, causando bugs difíceis de rastrear. Com o lockfile versionado, todos usam exatamente as mesmas versões.

# Adicione o lockfile ao repositório
git add composer.lock
git commit -m "Adiciona lockfile para garantir versões consistentes"

A pasta vendor/, por outro lado, não deve ser versionada. Adicione-a ao .gitignore:

/vendor/

5. Atualizando dependências com composer update

Enquanto composer install respeita o lockfile, composer update o ignora e resolve novamente as dependências, atualizando o composer.lock com as novas versões que respeitam as constraints definidas no composer.json.

# Atualiza todas as dependências
composer update

# Atualiza apenas um pacote específico
composer update monolog/monolog

A principal diferença prática é: use composer install em ambientes de produção e no dia a dia da equipe (para manter consistência), e use composer update quando você ativamente quiser atualizar versões.

As constraints de versão no composer.json determinam o limite das atualizações. Se você definiu "monolog/monolog": "^2.0", o composer update só atualizará para versões 2.x, nunca para 3.0. Para atualizar para uma nova versão major, você precisa alterar manualmente a constraint no composer.json.

6. Resolvendo conflitos e problemas comuns

Conflitos de dependência são inevitáveis em projetos complexos. Quando duas bibliotecas exigem versões incompatíveis de uma mesma dependência, o Composer exibe mensagens de erro detalhadas.

Para rastrear por que um pacote está sendo exigido:

composer why monolog/monolog

Para verificar por que uma versão específica não pode ser instalada:

composer why-not monolog/monolog 3.0

Se o cache do Composer causar problemas, limpe-o e reinstale as dependências do zero:

composer clear-cache
rm -rf vendor composer.lock
composer install

7. Boas práticas para o dia a dia com Composer

Além de versionar o composer.lock e ignorar vendor/, algumas práticas melhoram a experiência:

Scripts personalizados no composer.json automatizam tarefas comuns:

{
    "scripts": {
        "post-install-cmd": [
            "php artisan cache:clear"
        ],
        "post-update-cmd": [
            "php artisan optimize"
        ],
        "test": "phpunit"
    }
}

Para executar: composer test

Autoloading otimizado para produção reduz o tempo de carregamento das classes:

composer dump-autoload -o

Isso gera um autoloader com mapas de classe otimizados, eliminando a necessidade de varrer diretórios em cada requisição.

Por fim, mantenha o composer.json organizado, com dependências bem definidas e versões explicitamente controladas. Isso facilita a manutenção e evita surpresas desagradáveis em atualizações futuras.


Referências