O Composer é muito mais do que um simples gerenciador de dependências. Ele oferece recursos avançados que permitem automatizar tarefas, controlar versões com precisão, separar ambientes de desenvolvimento e produção, e até mesmo distribuir seus próprios pacotes. Nesta aula, vamos explorar esses recursos em profundidade, com exemplos práticos que você pode aplicar imediatamente em seus projetos.

Dominar o Composer avançado é essencial para qualquer desenvolvedor PHP profissional, pois impacta diretamente na manutenibilidade, segurança e eficiência do seu código. Vamos começar pelos scripts, que automatizam tarefas repetitivas.

Scripts

Os scripts do Composer permitem executar comandos personalizados em momentos específicos do ciclo de vida do projeto, como após a instalação de dependências ou antes de publicar uma nova versão. Eles são definidos no arquivo composer.json na seção scripts e podem ser chamados diretamente via composer run-script ou acionados automaticamente por eventos.

Os eventos mais comuns incluem pre-install-cmd, post-install-cmd, pre-update-cmd, post-update-cmd, pre-autoload-dump, post-autoload-dump, entre outros. Você também pode criar scripts personalizados para executar qualquer comando do sistema ou do PHP.

Exemplo de scripts básicos:

{
    "scripts": {
        "post-install-cmd": [
            "@php artisan migrate"
        ],
        "post-update-cmd": [
            "@php artisan optimize"
        ],
        "test": "phpunit",
        "lint": "phpcs --standard=PSR12 src/"
    }
}

Para executar um script personalizado, use composer test ou composer run-script test. Você também pode encadear scripts com @ para referenciar outros scripts, como "all": ["@lint", "@test"].

Além disso, é possível passar argumentos adicionais ao script: composer test -- --filter=testMethod.

Versionamento (semver)

O Composer utiliza o Versionamento Semântico (SemVer) para gerenciar versões de pacotes. O formato é MAJOR.MINOR.PATCH, onde MAJOR indica mudanças incompatíveis, MINOR adiciona funcionalidades compatíveis e PATCH corrige bugs. Entender isso é crucial para definir corretamente as restrições de versão no seu composer.json.

As restrições mais comuns são:

  • ^1.2.3 – permite atualizações até a próxima versão MAJOR (>=1.2.3 <2.0.0).
  • ~1.2.3 – permite atualizações até a próxima versão MINOR (>=1.2.3 <1.3.0).
  • 1.2.* – permite qualquer patch dentro da versão 1.2.
  • >=1.2.3 – permite qualquer versão maior ou igual.

Exemplo de restrições no composer.json:

{
    "require": {
        "php": ">=8.1",
        "monolog/monolog": "^3.0",
        "guzzlehttp/guzzle": "~7.0",
        "symfony/console": "6.2.*"
    }
}

Além disso, o Composer suporta stability flags para pacotes em desenvolvimento, como @dev, @alpha, @beta, @RC. Por exemplo, "vendor/package": "^1.0@beta".

Para garantir consistência, sempre use restrições flexíveis que permitam atualizações de segurança, mas evite * ou dev-master em produção, pois podem quebrar a aplicação.

require-dev

A seção require-dev define dependências necessárias apenas para desenvolvimento e testes, como PHPUnit, PHPStan, ou ferramentas de análise de código. Elas não são instaladas em produção quando você usa composer install --no-dev.

Isso mantém o ambiente de produção enxuto e reduz riscos de segurança. Exemplo:

{
    "require": {
        "php": ">=8.1",
        "monolog/monolog": "^3.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^10.0",
        "squizlabs/php_codesniffer": "*"
    }
}

Para instalar apenas dependências de produção, use composer install --no-dev ou composer update --no-dev. Isso é comumente feito em pipelines de CI/CD para deploys.

Você também pode usar scripts específicos para desenvolvimento, como "post-install-cmd": ["@php artisan migrate"] e "post-update-cmd": ["@php artisan optimize"], mas lembre-se de que esses scripts rodam mesmo com --no-dev a menos que você os condicione.

Pacotes próprios

Publicar seus próprios pacotes no Packagist ou em um repositório privado é uma habilidade valiosa. Para isso, você precisa criar um pacote com uma estrutura padrão, definir o composer.json e versioná-lo com Git.

Passos principais:

  1. Crie uma estrutura de diretórios: src/ para o código, tests/ para testes, e o arquivo composer.json na raiz.
  2. Defina o nome do pacote no formato vendor/package (use seu nome de usuário ou organização).
  3. Configure o autoload PSR-4 para mapear o namespace para src/.
  4. Defina a versão inicial usando tags Git (ex: 1.0.0).
  5. Publique no Packagist ou use um repositório privado com autenticação.

Exemplo de composer.json para um pacote:

{
    "name": "meu-vendor/meu-pacote",
    "description": "Um pacote de exemplo",
    "type": "library",
    "license": "MIT",
    "autoload": {
        "psr-4": {
            "MeuVendor\\MeuPacote\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "MeuVendor\\MeuPacote\\Tests\\": "tests/"
        }
    },
    "require": {
        "php": ">=8.1"
    },
    "require-dev": {
        "phpunit/phpunit": "^10.0"
    }
}

Para consumir seu pacote em outro projeto, adicione ao composer.json:

{
    "require": {
        "meu-vendor/meu-pacote": "^1.0"
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/meu-usuario/meu-pacote.git"
        }
    ]
}

Se o pacote for privado, você precisará configurar autenticação via SSH ou tokens. Além disso, para publicar no Packagist, basta criar uma conta e submeter a URL do repositório Git.

Boas práticas e observações finais

Ao trabalhar com Composer, sempre mantenha o composer.lock sob controle de versão para garantir que todos usem exatamente as mesmas versões. Em produção, use composer install (sem update) para respeitar o lock.

Evite depender de pacotes com dev-master ou @dev em produção, pois são instáveis. Prefira versões estáveis e atualize regularmente com composer update em um ambiente de desenvolvimento.

Documente seus scripts e restrições de versão para que outros desenvolvedores entendam o fluxo. E, ao criar pacotes, siga as boas práticas de PSR-4, teste com PHPUnit e inclua documentação.

Exercícios

  1. Crie um script personalizado chamado deploy que execute php artisan migrate --force e depois php artisan config:cache. Mostre como executá-lo.
  2. Explique a diferença entre as restrições ^1.2.3 e ~1.2.3 e dê exemplos de versões permitidas para cada uma.
  3. Adicione uma dependência de desenvolvimento phpunit/phpunit na versão ^10.0 e mostre como instalar sem as dependências de produção.
  4. Descreva os passos para publicar um pacote chamado meu-vendor/meu-pacote no Packagist, incluindo a estrutura de diretórios e o composer.json mínimo.
  5. Crie um composer.json que utilize require-dev com phpstan/phpstan e um script analyze que execute phpstan analyse src. Mostre o arquivo completo.

✓ Resposta: No composer.json, adicione:
"scripts": {
    "deploy": [
        "@php artisan migrate --force",
        "@php artisan config:cache"
    ]
}
Para executar: composer deploy.

✓ Resposta: ^1.2.3 permite versões >=1.2.3 e <2.0.0 (atualizações de menor e patch, mas não de maior). ~1.2.3 permite >=1.2.3 e <1.3.0 (apenas patches). Exemplo: com ^1.2.3, versões como 1.2.5, 1.3.0, 1.9.9 são permitidas; com ~1.2.3, apenas 1.2.x (ex: 1.2.4, 1.2.9).

✓ Resposta: Adicione em composer.json:
"require-dev": {
    "phpunit/phpunit": "^10.0"
}
Execute composer install --no-dev para instalar apenas as dependências de produção. Para instalar com dev, use composer install.

✓ Resposta: Passos: 1) Crie uma estrutura com src/ e tests/. 2) Crie o composer.json com nome meu-vendor/meu-pacote, autoload PSR-4. 3) Inicialize um repositório Git e faça commit. 4) Crie uma tag v1.0.0. 5) Publique o repositório no GitHub. 6) Submeta a URL do repositório no Packagist. O composer.json mínimo:
{
    "name": "meu-vendor/meu-pacote",
    "autoload": {
        "psr-4": {
            "MeuVendor\\MeuPacote\\": "src/"
        }
    },
    "require": {
        "php": ">=8.1"
    }
}

✓ Resposta:
{
    "require-dev": {
        "phpstan/phpstan": "^1.10"
    },
    "scripts": {
        "analyze": "phpstan analyse src"
    }
}

Referências