DevTips – Namespaces em PHP

Publicados: 2020-03-06

Há cerca de um ano, o WordPress decidiu atualizar a versão mínima exigida do PHP, de 5.2 (usada desde 2010) para algo mais atualizado. Na verdade, hoje a versão mínima do PHP recomendada pelo WordPress é uma das mais recentes: PHP 7.3.

Se você é um usuário simples do WordPress, isso provavelmente não o afetará muito (além do fato de que essas novas versões oferecem melhor desempenho).

Mas se você é um desenvolvedor, essas novas versões do PHP têm alguns recursos incríveis que você pode usar em seus plugins e temas. E hoje, especificamente, gostaria de falar com vocês sobre um que está conosco há muito tempo, mas: namespaces.

WordPress e prefixos de código

Uma das primeiras regras que você aprende como desenvolvedor do WordPress é “usar prefixos em tudo o que fazemos” para evitar “colisões de nomes”. Como podemos ler nas melhores práticas do WordPress:

Uma colisão de nomenclatura acontece quando seu plugin está usando o mesmo nome para uma variável, função ou classe de outro plugin.

[Para evitar colisões de nomes], todas as variáveis, funções e classes devem ser prefixadas com um identificador único. Os prefixos evitam que outros plugins sobrescrevam suas variáveis ​​e chamem acidentalmente suas funções e classes. Isso também impedirá que você faça o mesmo.

Práticas recomendadas para desenvolver plugins WordPress

Assim, por exemplo, em vez de criar uma função como get_site_id , é melhor nomeá-la nelio_content_get_site_id . Desta forma, conseguimos identificar rapidamente o plugin ( nelio_content ) ou tema ao qual uma determinada função ( get_site_id ) pertence e evitar erros fatais caso vários plugins tentem definir a mesma função.

Usar prefixos é uma forma rudimentar de criar um “namespace”; uma solução alternativa que tivemos que implementar quando não tínhamos uma alternativa melhor. Todos os elementos que usam o mesmo prefixo fazem parte do mesmo conjunto ou namespace. Mas isso resulta em um código desnecessariamente mais complexo: os nomes são mais longos por causa de prefixos que não servem para nada além de emular namespaces.

Namespaces PHP

O PHP versão 5.3 introduziu o conceito de namespace . A definição que eles dão na documentação me parece excelente, então eu a reproduzo aqui:

Na definição mais ampla, os namespaces são uma forma de encapsular itens. Isso pode ser visto como um conceito abstrato em muitos lugares. Por exemplo, em qualquer sistema operacional, os diretórios servem para agrupar arquivos relacionados e atuam como um namespace para os arquivos contidos neles. Como exemplo concreto, o arquivo foo.txt pode existir tanto no diretório /home/greg quanto em /home/other , mas duas cópias de foo.txt não podem coexistir no mesmo diretório.

No mundo PHP, os namespaces são projetados para resolver dois problemas que os autores de bibliotecas e aplicativos encontram ao criar elementos de código reutilizáveis, como classes ou funções:

1. Nomeie as colisões entre o código que você cria e o código PHP interno ou código de terceiros.

2. Capacidade de alias (ou encurtamento) Extra_Long_Names , melhorando a legibilidade do código-fonte.

Documentos PHP

Como criar um namespace

Criar um namespace em PHP é extremamente fácil. No início do arquivo PHP que você cria, adicione uma diretiva de namespace com o nome que você deseja usar e “tudo” que você definir nesse arquivo pertencerá a esse namespace:

 <?php namespace Nelio_Content;

Sim, é tão simples! Agora “tudo” que criarmos estará no namespace Nelio_Content . Por exemplo, se eu definir uma função como a que mencionei no início:

 <?php namespace Nelio_Content; function get_site_id() { // ... }

agora sabemos que get_site_id está dentro do namespace Nelio_Content . Dessa forma, não precisamos mais usar o prefixo nelio_content_ ao definir a função. Excelente!

Exceções aos namespaces

Se você observar atentamente o que eu disse até agora, você verá que eu escrevi “tudo” entre aspas: “'tudo' que adicionarmos lá pertencerá ao namespace especificado”. Por que eu fiz isso? Como os namespaces não se aplicam a absolutamente todos os códigos que escrevemos... existem algumas exceções.

Os namespaces PHP cobrem apenas os seguintes elementos PHP:

  • Aulas
  • Interfaces
  • Características
  • Funções
  • Constantes declaradas com const mas não com define

Além disso, existem algumas coisas adicionais no WordPress que também precisam de seus próprios namespaces e, infelizmente, namespaces PHP não cobrem: seus identificadores de script, opções de banco de dados ou tipos de conteúdo personalizados e seus metadados, etc. Em todos esses casos, você deve continue usando prefixos.

Como importar elementos de um namespace para outro

Se você precisar usar um elemento que está em seu próprio namespace, não precisa fazer nada de especial: basta chamá-lo pelo nome. Por exemplo, no trecho de código a seguir:

 <?php namespace Nelio_Content; function get_site_id() { // ... } function get_auth_token() { $site_id = get_site_id(); // ... }

Você pode ver que definimos duas funções: get_site_id e get_auth_token , ambas dentro do namespace Nelio_Content . Quando get_auth_token precisa usar get_site_id , ele simplesmente o chama normalmente.

Se, por outro lado, você precisar usar get_site_id em um namespace diferente, deverá chamar a função usando seu identificador completo:

 <?php namespace Something_Else; function do_some_action() { $site_id = Nelio_Content\get_site_id(); // ... }

ou você deve importar a função com a palavra-chave use :

 <?php namespace Something_Else; use Nelio_Content\get_site_id; function do_some_action() { $site_id = get_site_id(); // ... }

Eu pessoalmente gosto muito da segunda opção: usando a palavra-chave use para importar funções de outros namespaces, você pode dar uma olhada rápida no cabeçalho do seu arquivo e identificar suas dependências.

Filtros e ações do WordPress com namespaces PHP

Há um detalhe importante que você deve ter em mente ao usar namespaces ao lado de filtros e ações do WordPress. Quando você especifica retornos de chamada de filtro e ação, geralmente você faz isso fornecendo o nome do retorno de chamada como uma string:

 <?php // ... add_action( 'init', 'do_some_action' );

O problema é que se esta função estiver dentro de um namespace, o gancho anterior não funcionará conforme o esperado; você deve informar ao WordPress o nome completo da função. Em outras palavras, você deve incluir seu namespace (se houver).

Você está adicionando o gancho no arquivo onde você define o próprio namespace? Não importa, use o nome completo:

 <?php namespace Nelio_Content; function do_some_action() { // ... } add_action( 'init', 'Nelio_Content\do_some_action' );

Você está em outro namespace, mas importou a função com use ? Também não importa, use o nome completo:

 <?php namespace Something_Else; use Nelio_Content\do_some_action; // ... add_action( 'init', 'Nelio_Content\do_some_action' );

Usando aliases com nossos namespaces

Outra funcionalidade muito interessante de namespaces é o alias. Imagine o seguinte cenário:

 <?php namespace Nelio_Content; function get_site_id() { // ... }

Se eu quiser usar essa função em outro namespace, já vimos que posso fazer isso com use . Mas como eu usaria essa função se o módulo em que quero usá-la já tiver uma função chamada get_site_id ?

Bem, felizmente para mim, podemos apelidar nossas importações em novos nomes:

 <?php namespace Something_Else; use Nelio_Content\get_site_id as get_nc_site_id(); function get_site_id() { // ... } function do_some_action() { $nc_site_idd = get_nc_site_id(); // ... }

Comece a usar namespaces hoje!

Os namespaces são uma ferramenta fantástica para evitar colisões de nomes e organizar nosso código. Na verdade, e embora eu não tenha comentado neste post, existem padrões como o PSR-4 que permitem que o PHP carregue automaticamente classes com base na estrutura de namespaces que você usa e como você organiza o código em diretórios e arquivos.

Se você ainda não estiver usando namespaces em seus projetos, recomendamos que comece a fazê-lo a partir de agora. Conte-nos sobre sua experiência nos comentários!

Imagem em destaque por Chaitanya Tvs no Unsplash.