PHP-FIG e as PSR: Parte 4
Já falamos sobre o Padrão Básico de Codificação (PSR-1), sobre o Guia de Estilo de Codificação (PSR-2) e sobre a Interface de Logger (PSR-3). Agora, vamos falar sobre a PSR-4 e sua antecessora, a PSR-0.
A PSR-0 foi depreciada em outubro de 2014, em prol da PSR-4, ambas definem regras de autoloading. Vamos conhecer primeiro a PSR-0, e depois sua sucessora, a PSR-4.
Vale lembrar que, para melhor entendimento, é legal você já ter lido sobre a PSR-1, a PSR-2 e a PSR-3. Caso você não tenha lido, pode ler nestes links:
Antes de mais nada, precisamos ter em mente o que é um autoloader. A maioria dos desenvolvedores já sabem do que se trata, mas para todos os efeitos, considere o autoloader como uma classe que, como o próprio nome diz, é um carregador automático de outras classes, ou seja: fazendo uso de um autoloader, você não precisa ficar dando require (ou include) em todas as classes do seu sistema. Basta instanciar ou chamar qualquer método de uma classe e ela será carregada automaticamente.
PSR-0: Autoloading Standard
“Esta PSR define as regras que devem ser aderidas para garantir a interoperabilidade do autoloader.”
Vamos falar sobre essa PSR apenas para fins de conhecimento, mas por ter sido depreciada, não é recomendado utilizar a PSR-0, e sim a PSR-4, que tem os mesmos fins mas aplicados de formas mais inteligentes.
Uma diferença que vamos notar na PSR-0, é que ela não trabalha com as chaves que separam a aplicação de cada regra (DEVE, NÃO DEVE, etc.). Nesta PSR, todas as regras são obrigatórias, então considere que em todos os itens temos um DEVE. Vamos lá:
Regras obrigatórias da PSR-0:
Os nomes completos de namespaces e classes devem seguir a seguinte estrutura: \Vendor\(\)*.
Todas as classes do seu sistema precisam seguir a mesma estrutura de namespaces, que é o formato mencionado acima. No segundo item da estrutura, note que podem existir vários namespaces até chegarmos numa classe, logo, as estruturas abaixo são válidas:
namespace \MeuFramework\MinhaBiblioteca\MinhaClasse; namespace \MeuFramework\MinhaBiblioteca\OutraBiblioteca\OutraClasse;
Cada namespace deve ter um namespace raíz.
Sempre que definir um namespace, tenha certeza de colocá-lo dentro do namespace raiz, ou seja, no caso do nosso exemplo acima, seria o \MeuFramework\.
Sempre que definir um namespace, tenha certeza de colocá-lo dentro do namespace raiz, ou seja, no caso do nosso exemplo acima, seria o \MeuFramework\.
Cada namespace pode ter quantos sub-namespaces forem necessários
Como já vimos acima, você pode colocar a sua classe dentro de quantos namepaces precisar.
Como já vimos acima, você pode colocar a sua classe dentro de quantos namepaces precisar.
No momento do carregamento de arquivos, o separador de namespaces (\) precisa ser convertido em um DIRECTORY_SEPARATOR.
Sempre que seu autoloader for buscar uma classe, ao ler o namespace dela, ele precisa substituir cada caractere “\” com o valor da constante DIRECTORY_SEPARATOR (que geralmente é uma “/”). Isso deve ser feito para o seu autoloader conseguir navegar no sistema de arquivos e encontrar a classe desejada.
Sempre que seu autoloader for buscar uma classe, ao ler o namespace dela, ele precisa substituir cada caractere “\” com o valor da constante DIRECTORY_SEPARATOR (que geralmente é uma “/”). Isso deve ser feito para o seu autoloader conseguir navegar no sistema de arquivos e encontrar a classe desejada.
Cada caractere “_” no nome da classe precisa ser convertido em um DIRECTORY_SEPARATOR. Este caractere não tem nenhum efeito no namespace.
Seguindo a mesma ideia da regra acima, sempre que o seu autoloader encontrar um underscore (_) no nome da classe (somente no nome da classe, e não no namespace), ele deve converter esse underscore em um DIRECTORY_SEPARATOR. Logo, se você tem uma classe chamada \MeuFramework\MeuNamespace\Minha_Classe, a estrutura de diretórios deve ser MeuFramework/MeuNamespace/Minha/Classe, e o nome da classe deve ser apenas Classe.
Seguindo a mesma ideia da regra acima, sempre que o seu autoloader encontrar um underscore (_) no nome da classe (somente no nome da classe, e não no namespace), ele deve converter esse underscore em um DIRECTORY_SEPARATOR. Logo, se você tem uma classe chamada \MeuFramework\MeuNamespace\Minha_Classe, a estrutura de diretórios deve ser MeuFramework/MeuNamespace/Minha/Classe, e o nome da classe deve ser apenas Classe.
No momento do carregamento, o autoloader deve adicionar o sufixo “.php” no nome completo da classe (incluindo o namespace).
Bem simples também: se o seu autoloader recebe a tarefa de carregar a classe \MeuFramework\MeuNamepace\MinhaClasse, ele deve adicionar “.php” no final desse parâmetro recebido.
Bem simples também: se o seu autoloader recebe a tarefa de carregar a classe \MeuFramework\MeuNamepace\MinhaClasse, ele deve adicionar “.php” no final desse parâmetro recebido.
Caracteres alfabéticos nos namespaces e classes podem ser definidas em qualquer combinação de letras maiúsculas e minúsculas.
Essa regra é auto-explicativa: não existe regra quanto a formatação do nome de classes ou namespaces.
Essa regra é auto-explicativa: não existe regra quanto a formatação do nome de classes ou namespaces.
Esta é a PSR-0, como podemos ver, são poucas regras, mas algumas delas interferem em outras PSR, além de não serem regras exatamente cabíveis para sistemas atuais. Não vamos entrar em detalhes pois como já sabemos, essa PSR foi depreciada e não deve mais ser utilizada. Ao implementar um autoloader, devemos usar a PSR-4.
PSR-4: Autoloading melhorado
“Esta PSR descreve uma especificação para classes de autoload a partir de caminhos de arquivos. É 100% interoperável e pode ser utilizada em conjunto com qualquer outra especificação de autoload, incluindo a PSR-0. Esta PSR também define onde colocar os arquivos que serão carregados automaticamente”.
Essa PSR foi repensada e escrita para trabalhar com as outras PSR, e em outubro de 2014 passou a ser a PSR recomendada para autoloaders.
O nome completo da classe DEVE possuir um namespace raiz.
Assim como na PSR-0, sempre que definirmos um namespace ou classe, precisamos colocá-lo dentro do nosso namespace raiz, que geralmente é o nome do nosso sistema ou framework.
Assim como na PSR-0, sempre que definirmos um namespace ou classe, precisamos colocá-lo dentro do nosso namespace raiz, que geralmente é o nome do nosso sistema ou framework.
O nome completo da classe PODE possui um ou mais sub-namespaces.
Esta regra também está presente na PSR-0: nós podemos usar quantos sub-namespaces quisermos, desde que estejam dentro do nosso namespace raiz.
Esta regra também está presente na PSR-0: nós podemos usar quantos sub-namespaces quisermos, desde que estejam dentro do nosso namespace raiz.
O nome completo da classe DEVE terminar com o nome de uma classe.
Sempre que um autoloader chamar uma classe, ele vai considerar tudo o que depois da última “\” como o nome da classe, e antes, o(s) namespace(s).
Sempre que um autoloader chamar uma classe, ele vai considerar tudo o que depois da última “\” como o nome da classe, e antes, o(s) namespace(s).
Underscores (_) NÃO DEVEM possuir efeito especial em nenhuma parte do nome completo da classe.
Diferente da PSR-0, o “_” não precisa ser convertido em um separador de diretórios nem nada do tipo. Um “_” no nome da classe/namespace significa apenas um “_”.
Diferente da PSR-0, o “_” não precisa ser convertido em um separador de diretórios nem nada do tipo. Um “_” no nome da classe/namespace significa apenas um “_”.
Caracteres alfabéticos nos namespaces e classes PODEM ser definidas em qualquer combinação de letras maiúsculas e minúsculas.
Assim como na PSR-0, ao definir um nome de classe, não existe regra quanto a formatação do nome completo (tanto namespace quando nome da classe).
Assim como na PSR-0, ao definir um nome de classe, não existe regra quanto a formatação do nome completo (tanto namespace quando nome da classe).
Todos os nomes de classes DEVEM ser referenciados de forma sensível a capitalização (case-sensitive).
Quando o autoloader for chamar uma classe, ele deve utilizar o nome real da classe, respeitando as letras maiúsculas e minúsculas.
Quando o autoloader for chamar uma classe, ele deve utilizar o nome real da classe, respeitando as letras maiúsculas e minúsculas.
Quando estiver carregando um arquivo correspondente a um nome completo de classe (\Namespace\Classe): uma série de um ou mais namepaces, não incluindo o namespace global (primeiro \), DEVE corresponder a pelo menos um diretório base; Cada sub-namespace definido depois do namespace global (primeiro \) corresponde a um subdiretório dentro do diretório base. O nome do subdiretório DEVE ser escrito da mesma forma que o nome do sub-namespace (respeitando maiúsculas e minúsculas); A classe chamada depois dos namespaces DEVE corresponder a um arquivo .php. O nome do arquivo DEVE ser escrito da mesma forma que o nome da classe (respeitando maiúsculas e minúsculas)
Basicamente, pelo menos o primeiro namespace utilizado deve corresponder ao diretório base do seu sistema ou framework, por exemplo: se você tem um framework chamado MeuFramework, o namespace padrão dele será \MeuFramework\, então você precisa colocar todas as classes desse framework dentro da pasta MeuFramework, ficando MeuFramework\MinhaClasse.php, e isso se estende quando você tem sub-namespaces, ou seja: se o namespace é \MeuFramework\MeuModulo\MinhaClasse, o arquivo MinhaClasse.php deve estar dentro da pasta MeuFramework\MeuModulo, e assim por diante.
Basicamente, pelo menos o primeiro namespace utilizado deve corresponder ao diretório base do seu sistema ou framework, por exemplo: se você tem um framework chamado MeuFramework, o namespace padrão dele será \MeuFramework\, então você precisa colocar todas as classes desse framework dentro da pasta MeuFramework, ficando MeuFramework\MinhaClasse.php, e isso se estende quando você tem sub-namespaces, ou seja: se o namespace é \MeuFramework\MeuModulo\MinhaClasse, o arquivo MinhaClasse.php deve estar dentro da pasta MeuFramework\MeuModulo, e assim por diante.
Implementações de autoloader NÃO DEVEM lançar exceções, NÃO DEVEM gerar erros de nenhum nível e NÃO DEVERIAM retornar nenhum valor.
Um autoloader não deve fazer nada além do seu trabalho: realizar o carregamento automático. No caso de existir, por exemplo, uma chamada a uma classe e o autoloader não consiga encontrar, ele não deve fazer nada. Entende-se que é função do desenvolvedor se certificar de estar instanciando uma classe existente dentro do seu diretório base (e de subdiretórios, onde existir).
Um autoloader não deve fazer nada além do seu trabalho: realizar o carregamento automático. No caso de existir, por exemplo, uma chamada a uma classe e o autoloader não consiga encontrar, ele não deve fazer nada. Entende-se que é função do desenvolvedor se certificar de estar instanciando uma classe existente dentro do seu diretório base (e de subdiretórios, onde existir).
E com isso encerramos sobre a PSR-4. Neste link, você pode encontrar um exemplo de um autoloader que segue a PSR-4, criado pelo pessoal do PHP-FIG.
Agora já falamos sobre todas as PSR ativas até o momento (e uma depreciada). Nos próximos artigos falaremos sobre as PSR que ainda estão em processo de revisão ou desenvolvimento, então fique ligado!
Se você ficou com alguma dúvida, ou quer fazer algum comentário, é só deixar aí em baixo! :)