Composer e a Gestão de Dependências no PHP
O que é o Composer?
O Composer é essencialmente uma maneira de incluir todos os softwares de terceiros em seu projeto. Ele permite que você declare as bibliotecas que seu projeto precisa para funcionar e com o Composer você gerencia (instala/atualiza/remove) tais dependências.
Instalando
O Composer está disponível para os principais sistemas operacionais. Em sistemas baseados em Linux, você pode usar os seguintes comandos:
Como funciona?
Existem duas vertentes para o gerenciamento de dependências no PHP com o Composer. A primeira é o próprio Composer que é uma ferramenta de linha de comandos para gerenciar as dependências. E a segunda é Packagist, o principal repositório onde o código dos pacotes que você deseja usar são armazenados.
Ao usar o Composer, a base do gerenciamento de dependências, será o arquivo composer.json, se liga:
As dependências do seu projeto podem ser listadas em require ou require-dev. E já me antecipando, a diferença entre eles é: no require deve ficar tudo o que é necessário para o projeto funcionar, do lado do require-dev, devem ficar pacotes que serão usados em apoio ao desenvolvimento, como é o caso do PHPUnit por exemplo.
Para instalar os pacotes é super simples, usando o terminal, na pasta do seu projeto, é só digitar o comando install:
composer install
As dependencias listadas no composer.json vão ser instaladas todas de uma vez só. Mas você também pode querer instalar os pacotes sob demanda conforme for surgindo a necessidade de uso deles, essa também é uma tarefa fácil usando o comando require, olha só:
composer require --dev phpunit/phpunit ^8.5
Para atualizar as dependências também é simples demais, basta usar o comando update, olha o exemplo:
composer update
Mas se você quiser atualizar somente um pacote:
composer update phpunit/phpunit
Mas tu quer uma versão especifica? Sem problemas!
composer update phpunit/phpunit:9.5
Versionamento
No exemplo, eu disse para o Composer que eu queria especificamente a versão 1.12.0 do monolog, mas tem casos em que queremos ser um pouco mais tolerantes, e para fazer isso temos algumas opções, saca só:
Version Range
Usando operadores de comparação, você pode obter uma versão superior a 2.0, inferior a 2.9 ou seguir um conjunto de regras ainda mais complexo usando a lógica AND e OR. Os seguintes operadores podem ser usados: >, <, >=, <=e !=. Lógica AND é representado por um espaço ou uma vírgula, OR lógica é representada por tubulações duplas: ||.
Especificar >2.7 significaria qualquer versão acima de 2.7. >2.7 <=3.5 permitiria qualquer versão acima de 2.7 até — e incluindo — 3.5.
Wildcard
Usando um curinga, você pode especificar um padrão. 2.3.* abrangeria tudo acima e incluindo 2.3.0 e abaixo — mas não incluindo — 2.4.0. Exemplo: >= 2.3.0 < 2.4.
Til
Um intervalo de til é ótimo para definir uma versão mínima necessária e permitir qualquer coisa até, mas não incluindo, a próxima versão principal. Se você especificar, ~3.6 está permitindo o 3.6 e tudo até, mas não incluindo o 4.0.
Este método de especificar uma versão é equivalente a >-3.6 <4.0.
Caret
Tem o funcionamento semelhante ao Til(~), ficando mais parecido ao Semantic Versioning, permitindo atualizações não bloqueantes e constantes. Por exemplo ^1.2.3, quer dizer que qualquer update do pacote nesse intervalo >=1.2.3 < 1.9.x, vai ser aceito, pois nenhuma das versões até 1.9.x deve quebrar a compatibilidade com versões anteriores.
Dev-Master
Ao especificar que dev-master você está obtendo a versão mais recente desenvolvida atualmente, a qual ainda não foi marcada com um número de versão. Isso pode ser bom durante o desenvolvimento, mas você precisa estar ciente de que o potencial para bugs é maior nessas versões.
Bloqueando as dependências
O bloqueio de versões dos componentes é um dos recursos mais úteis do Composer e o que faz isso acontecer é justamente composer.lock que falei anteriormente.
O arquivo de bloqueio pode garantir que todos trabalhem com as mesmas versões de arquivos. Só porque o aplicativo não deve ser interrompido devido a uma atualização de componente, não significa que todos os seus colegas de equipe e o servidor de produção devem estar executando versões separadas.
Quando você usa o Composer pela primeira vez para obter uma dependência, ele grava a versão exata no arquivo de bloqueio. Se você especificou 2.3.* e 2.3.5 como a versão mais recente, a versão instalada será 2.3.5 e será inserida no arquivo de bloqueio.
Digamos que um desenvolvedor se junte à equipe 10 dias depois. Neste momento, a dependência foi atualizada para 2.3.6. Se ele usar o comando correto (composer install) ele receberá 2.3.5 porque está travado no lugar.
Claro, você pode decidir atualizar suas dependências. Nesse caso, você deve usar o comando composer update. Isso irá trazer as versões mais recentes permitidas e gravá-las no composer.lock e então será distribuído a todas as fontes que por sua vez podem ser atualizadas.