Desenvolvimento

9 dez, 2013

Composer e PSR-0: Amigos, mas não parentes

Publicidade

Como um grande defensor do Composer, um usuário feliz do PSR-0 e um membro votante no PHP-FIG, eu entro em muitas conversas sobre todos eles, e me preocupa a confusão que existe na comunidade sobre essas coisas não sendo relacionadas.

Para muitos de vocês, isso será chover no molhado, mas irá esclarecer algumas coisas para muitos ou, pelo menos, ser um recurso útil para ligar as pessoas para quando elas mostrarem sinais de confusão entre os dois. Me desculpe se isso chateia você.

  1. PSR-0 foi lançado em 2009
  2. Composer foi lançado em 2011
  3. Composer suporta PSR-0
  4. Código PSR-0 pode ser instalado e carregado automaticamente usando Composer

Parece que um monte de gente descobriu Composer e PSR-0 ao mesmo tempo e assume que eles são a mesma coisa – especialmente porque ambos têm a ideia de um “vendedor ” e um “pacote”, mas essas duas coisas não estão relacionadas umas com as outras também.

Estes são alguns pontos que eu queria esclarecer durante algumas conversas estranhas ao longo das últimas semanas.

Confusão com o Vendor Name

Esta surge com bastante frequência, e foi perguntada na lista de discussão composer-dev outro dia.

Se você usar PSR-0 e Composer, então você tem dois nomes diferentes de fornecedores e de pacotes.

Por quê? Porque mesmo código que não está usando o PSR-0 precisa de nomes de vendedores e de pacotes, de modo que um código como o Facebook SDK pode ser feito em Composer compatível apenas adicionando um composer.json, e não precisa ser recodificado para PSR-0.

• Facebook => vendor/facebook/php-sdk/src/facebook.php

Se você quiser usar PSR-0 para suas classes, então você precisa criar fornecedores e pacotes no PHP também, mas lembre-se de que o seu código poderia não estar de acordo com a PSR- 0, então você ainda precisa desses fornecedores específicos para o Composer em seu código. Isso significa que o pacote poderia ser assim:

• Phil\Kitten\Snuggles => vendor/phil/kittens/src/Phil/Kitten/Snuggles.php

Agora, enquanto você pode ficar chateado por ter que ter dois lotes de fornecedores, você pode ver aqui que eles podem não ser idênticos. Eu poderia querer que meus namespaces PHP fossem singulares, e meu pacote Composer poderia muito bem ser plural.

Isso vale ainda mais quando se considera o fato de que namespaces PHP não permitem hifens, mas pacotes Composer sim.

• Symfony\Component\BrowserKit\Cookie => vendor/symfony/browser-kit/src/Symfony/Components/BrowserKit/Cookie.php

Ou esses nomes poderiam ser completamente diferentes de seus nomes Composer:

• Illuminate\Validation\ValidationServiceProvider => vendor/laravel/framework/src/Illuminate/Validation/ValidationServiceProvider.php

Por que isso é totalmente diferente? Porque Laravel é um framework, formado por muito componentes diferentes. Esses componentes estão sob o namespace “Illuminate” e podem ser usados em qualquer aplicativo que você quiser. Juntos, eles se tornam o framework Laravel.

Assim, esses dois têm nada a ver um com o outro, e não vamos assumir que eles precisam ser a mesma coisa, porque isso só cobre uma fração dos casos de uso que o PSR-0 suporta.

Dizer que pacotes Composer não são PSR-0

Isso surgiu tantas vezes e é bobagem .

Composer é voltado para suportar PSR-0, mas eu tenho todos esses diretórios em letras minúsculas.

Ter sub-diretórios como “src/”, “tests/” etc. não faz esse código não-PSR- 0. Os carregadores automáticos do PSR-0 são capazes de registrar vários pontos. Cada local que você registra é ligado a um prefixo namespace; em seguida, ele irá carregar a partir de lá. Se você estiver usando pacotes Composer, você vai apontar o prefixo para a sua pasta  src/:

"autoload": {
    "psr-0": { "Foo\Upload": "src" }
}

Tudo lá dentro é então considerado PSR-0, tudo o que está fora é irrelevante.

Então, esse código é especificamente obrigado a viver em Composer? Eu pensei que você tinha dito…?

Não. Esse código é desenvolvido para ser um componente, que agrupa sua src/, seus tests/ e um README. Ele passa a ser instalável pelo Composer, ou Unicorn (o gerente da dependência que eu inventei), mas poderia perfeitamente funcionar por conta própria, sem quebrar a especificação PSR-0.

Se você queria que esse código vivesse fora do composer, então você pode fazer uma de duas coisas:

  1. Copie e cole o conteúdo de src em um diretório PSR-0 principal na sua aplicação – como o 2001 – e use o autoloader de exemplo.
  2. Copiar e colar todo a base de código do componente e usar o SplClassLoader para registrar Foo\Upload no src/ você mesmo.

Fazer qualquer uma dessas coisas é um pouco estranho, porque… bem por que você as faria?

Se você quer instalar os componentes, então use algo que é projetado para instalá-los (Composer ou Unicorn ), e se você quer carregar automaticamente o seu próprio código, coloque-o diretamente em uma área automaticamente carregável dentro de sua aplicação.

PyroCMS faz ambos, ele tem:

  • system/cms/modules/*/src/
  • system/cms/src/
  • vendor/*/*/(lib/|src/)

Nota: Esse regex está ali apenas para destacar que os devs Composer podem fazer o que quiserem.

O ponto aqui é que PyroCMS suporta locais personalizados de carregamento automático do PSR-0 (um global, um em cada módulo) e um fornecedor principal/pasta que tem uma mistura de PSR-0 e código aleatório de classmap.

PSR-0 deve permanecer agnóstico sobre a implementação

Esta é uma outra conversa que tem aparecido algumas vezes. As pessoas querem ver o Composer fazendo mudanças para trazer suporte para o PSR-0 mais para o núcleo, ou querem que o PSR-0 mude com base em como o Composer funciona. Isso seria louco, e felizmente ninguém na FIG tem falado sobre ter qualquer interesse em fazer isso.

De forma realista, o Composer é o único gerenciador de dependência lá fora neste momento, mas, teoricamente, alguém poderia construir um sistema maior e melhor amanhã. Toda a comunidade PHP poderia se apaixonar imediatamente por esse gerenciador de dependência, jogando fora instantaneamente o Composer mais rápido do que madrastas cheias de peste em 1349, e que podiam dar suporte para o PSR-0 da mesma forma.

Talvez seja necessário fazer um arquivo unicorn.json para fica ao lado de seu composer.json, e ele poderia trabalhar com os dois sistemas com a mesma facilidade. Sem outras alterações seriam necessárias para mudar .

Ter uma especificação que se baseia em uma estrutura específica a ser criada por um pedaço de software de terceiros seria prejudicial para toda a comunidade, razão pela qual coisas como PHPab são impressionantes, mas não um padrão.

Composer deve permanecer agnóstico sobre a especificação

O que acontecerá quando um novo padrão de carregamento automático for liberado? Nós descobriremos muito em breve, já que o PHP-FIG estão trabalhando em uma proposta incrível chamada “Package Autoloader”. Isso está sendo chamado de PSR-X e, provavelmente será lançado como PSR-4, e é incrivelmente semelhante ao código PSR-0 com alguns ajustes muito úteis.

De forma simples, PSR-X já não traduz sublinhados para separadores de diretório (que estava lá para o tipo de legado PEAR/Zend) e permite que os desenvolvedores de pacotes pulem potencialmente o namespace PHP por inferir que:

• Symfony\Component\BrowserKit\Cookie => vendor/symfony/browser-kit/src/Cookie.php

Para que isso funcione, haverá uma implementação de exemplo um pouco diferente do carregador automático, que vai aceitar argumentos que basicamente transmitem a mensagem de que Symfony\Component\BrowserKit mapeia para vendor/symfony/browser-kit, e, em vez de exigir a estrutura da pasta extra, só vai começar a olhar para a próxima pasta ou arquivo. Em outras palavras, você simplesmente apaga as pastas Symfony/Components/BrowserKit e move tudo para algumas pastas. Simples!

Se o Composer tivesse sido todo amarrado no PSR-0, então isso nunca iria funcionar, e todo o material antigo iria quebrar. Do jeito que está, vai ser insanamente fácil para o Composer integrar suporte para PSR-X/PSR-4 ? no Composer. Haverá alguma lógica que vai para o composer.json, que será algo parecido com:

"autoload": {
    "psr-4": { "Foo\Upload": "src" }
}

Isso funcionaria exatamente igual, mas você simplesmente pula algumas pastas.

Composer, PSR-0, PSR- X e a separação deles é importante

O PSR-X precisa ser separado para evitar ferrar com os usuários do PSR-0. Ambos precisam ser separados do Composer para que o Composer faça suas coisas, enquanto eles fazem as deles.

Eu já ouvi algumas conversas sobre “o que é mais importante”, e eu acho que se perguntar sobre isso é inútil. PHP é um ecossistema, e em um ecossistema tudo tem o seu papel. As árvores são obviamente importantes, mas eu me lembro de ter uma conversa bêbado na qual alguém me explicou como o planeta Terra iria morrer, ao longo de algumas décadas, se não houvesse formigas.

Independentemente da história do tipo “um pássaro bate suas asas e nós temos dinossauros de novo” que você quer acreditar, é importante lembrar que cada parte de um ecossistema é importante. Se você odeia formigas, então não compre uma fazenda de formiga, ou vá para a floresta tropical, mas, se você matar todas elas, haverá um monte de tamanduás chateados. Ou algo assim.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://philsturgeon.co.uk/blog/2013/05/composer-and-psr0-friends-not-relatives