PHP 5.3 parte 1: Namespaces
Usando Namespaces
É possível referenciar os elementos de uma namespace em até 3 maneiras diferentes:
* Nome não qualificado. Exemplo de uma chamada de nome não qualificado: $a = new User(); Se a namespace corrente do arquivo for “Blog”, namespace Blog; , a declaração anterior será transformada para Blog\User();. Caso o código for global, ou seja, código sem namespace, será transformada para simplesmente User();
* Nome qualificado. São chamadas utilizando nomes relativos, quando usa-se sub-namespaces. Exemplo: namespace Company\Blog;. A seguinte declaração instancia a classe User utilizando “Nome Qualificado”: $a = new Blog\User();. Como a namespace raiz do arquivo é “Company”, a declaração anterior será transformada para Company\Blog\User();. Vamos ver a utilização de sub-namespaces mais adiante.
* Full Qualified Name. São chamadas utilizando nomes absolutos. Exemplo: $a = new \Blog\User(); $b = new \Cms\User(); $c = new \Company\Blog\User();
Vamos criar um novo arquivo para exemplificar a utilização de namespaces:
Arquivo TestNamespace.php:
A saída do script acima:
Nome não-qualificado
No exemplo anterior instanciamos as classes User de diferentes namespaces usando o full-qualified-name. Para ilustrar a chamada de uma classe usando nome não-qualificado vamos definir a namespace do arquivo TestNamespace.php para “Blog”:
Desta maneira temos o arquivo TesteNamespace.php na mesma namespace que a classe User do Arquivo UserBlog.php. Portanto no lugar de usar “\Blog\User();” podemos simplesmente usar:
Para instanciar a classe User do namespace Cms, continuamos a ter que usar o full-qualified-name.
Sub-namespaces
Semelhantes à diretórios e arquivos, namespaces em php podem ser declaradas em forma de hierarquia. Exemplo:
Nome Qualificado
Para exemplificar a chamada de uma classe usando nome qualificado vamos definir sub-namespaces em nossos 3 arquivos:
Troque a linha que define a namespace para cada um dos arquivos:
UserBlog.php
UserCms.php
TesteNamespace.php
Como todos os arquivos tem definido o namespace raiz para Project, podemos usar “nome-qualificado”, ou nome relativo, para acessar as classes dentro do arquivo TesteNamespace.php:
Automaticamente $user = new Blog\User() vai ser transformado para $user = new \Project\Blog\User(); e $user1 = new Cms\User(); vai ser resolvido para $user1 = new \Project\Cms\User(); de forma transparente.
É possível referenciar os elementos de uma namespace em até 3 maneiras diferentes:
* Nome não qualificado. Exemplo de uma chamada de nome não qualificado: $a = new User(); Se a namespace corrente do arquivo for “Blog”, namespace Blog; , a declaração anterior será transformada para Blog\User();. Caso o código for global, ou seja, código sem namespace, será transformada para simplesmente User();
* Nome qualificado. São chamadas utilizando nomes relativos, quando usa-se sub-namespaces. Exemplo: namespace Company\Blog;. A seguinte declaração instancia a classe User utilizando “Nome Qualificado”: $a = new Blog\User();. Como a namespace raiz do arquivo é “Company”, a declaração anterior será transformada para Company\Blog\User();. Vamos ver a utilização de sub-namespaces mais adiante.
* Full Qualified Name. São chamadas utilizando nomes absolutos. Exemplo: $a = new \Blog\User(); $b = new \Cms\User(); $c = new \Company\Blog\User();
Vamos criar um novo arquivo para exemplificar a utilização de namespaces:
Arquivo TestNamespace.php:
<?php // incluir as classes com mesmo nome, porém com diferentes namespaces. require_once("UserBlog.php"); require_once("UserCms.php"); // Instanciar class User do namespace Blog. Usando full qualified name. $user = new \Blog\User(); $user->setName("Douglas"); print $user->getName(); print PHP_EOL; // Instanciar class User do namespace Cms. Usando full qualified name. $user2 = new \Cms\User(); $user2->setName("Douglas"); print $user2->getName();
The username in Blog is Douglas The username in CMS is Douglas
Nome não-qualificado
No exemplo anterior instanciamos as classes User de diferentes namespaces usando o full-qualified-name. Para ilustrar a chamada de uma classe usando nome não-qualificado vamos definir a namespace do arquivo TestNamespace.php para “Blog”:
namespace Blog;
Desta maneira temos o arquivo TesteNamespace.php na mesma namespace que a classe User do Arquivo UserBlog.php. Portanto no lugar de usar “\Blog\User();” podemos simplesmente usar:
$user = new User();
Para instanciar a classe User do namespace Cms, continuamos a ter que usar o full-qualified-name.
Sub-namespaces
Semelhantes à diretórios e arquivos, namespaces em php podem ser declaradas em forma de hierarquia. Exemplo:
namespace Project\Blog;
Nome Qualificado
Para exemplificar a chamada de uma classe usando nome qualificado vamos definir sub-namespaces em nossos 3 arquivos:
Troque a linha que define a namespace para cada um dos arquivos:
UserBlog.php
namespace Project\Blog;
UserCms.php
namespace Project\Cms;
TesteNamespace.php
namespace Project;
Como todos os arquivos tem definido o namespace raiz para Project, podemos usar “nome-qualificado”, ou nome relativo, para acessar as classes dentro do arquivo TesteNamespace.php:
$user = new Blog\User(); // transformado para \Project\Blog\User(); ... $user1 = new Cms\User(); // transformado para \Project\Cms\User();
Automaticamente $user = new Blog\User() vai ser transformado para $user = new \Project\Blog\User(); e $user1 = new Cms\User(); vai ser resolvido para $user1 = new \Project\Cms\User(); de forma transparente.
Olá Diego,
O autoload é uma forma de carregar os arquivos de suas classes php dinâmicamente, sem a necessidade de ter que ficar usando require_once para cada arquivo de classe que você necessita carregar.
Quando usado autoload com namespace, o caminho todo do namespace será passado para a função autoload. Exemplo:
Será executada a função __autoload, com o parâmetro "\Cms\Usuario" . A partir daí é só usar essa informações para localizar o arquivo que deseja incluir! È necessário que você implemente a função __autoload.
O autoload é uma forma de carregar os arquivos de suas classes php dinâmicamente, sem a necessidade de ter que ficar usando require_once para cada arquivo de classe que você necessita carregar.
Quando usado autoload com namespace, o caminho todo do namespace será passado para a função autoload. Exemplo:
$user = new \Cms\Usuario();
Será executada a função __autoload, com o parâmetro "\Cms\Usuario" . A partir daí é só usar essa informações para localizar o arquivo que deseja incluir! È necessário que você implemente a função __autoload.
03/11/2010 5:14pm
(~14 anos atrás)
Vocês poderiam dar exemplos de autoload por namespace, achei essa parte muito confusa.
abraços
abraços
02/11/2010 4:36pm
(~14 anos atrás)
Rubens, Obrigado pelo toque sobre o autoload. Realmente é um recurso muito importante. Quando usamos autoload para incluir as classes usadas na aplicação, com o uso de namespace, o nome full-qualifed é passado para a função __autoload. Por exemplo:
No exemplo anterior, ao instanciar a classe User, o valor da variável $class_name passada para a função __autoload será Project\Cms\User. Neste caso do exemplo todas as classes estão no diretório lib. Caso você adicione um código na função de __autoload para obter somente o nome da classe e incluí-la, removendo a parte do namespace da string, não poderemos ter dois arquivos com o mesmo nome no mesmo diretório. Portanto, a melhor coisa a fazer realmente é criar uma estrutura de diretórios correspondente à hierarquia usada no namespace. O path completo do arquivo contendo a classe User do exemplo anterior seria:
lib/Project/Cms/user.php
Falta agora modificar a função de __autoload() para converter a string de namespace para o path do arquivo contendo a classe.
$user = new Project\Cms\User(); function __autoload($class_name) { require_once("lib/$class_name.php"); }
No exemplo anterior, ao instanciar a classe User, o valor da variável $class_name passada para a função __autoload será Project\Cms\User. Neste caso do exemplo todas as classes estão no diretório lib. Caso você adicione um código na função de __autoload para obter somente o nome da classe e incluí-la, removendo a parte do namespace da string, não poderemos ter dois arquivos com o mesmo nome no mesmo diretório. Portanto, a melhor coisa a fazer realmente é criar uma estrutura de diretórios correspondente à hierarquia usada no namespace. O path completo do arquivo contendo a classe User do exemplo anterior seria:
lib/Project/Cms/user.php
Falta agora modificar a função de __autoload() para converter a string de namespace para o path do arquivo contendo a classe.
function __autoload($class) { // converter namepsace para path completa do arquivo $class = 'classes/' . str_replace('\\', '/', $class) . '.php'; require_once($class); }
12/12/2009 11:41am
(~15 anos atrás)
Bacana o artigo, Douglas. Parabéns. Eu acho muito legal quando antecipam algumas funcionalidades previstas para o PHP 6, como o namespace.
Acho que só faltou um detalhe importante no seu artigo, que é o tratamento sobre o autoload de classes. Com namespace é possível definir qual autoload cuida de qual namespace. Também é possível organizar as classes em diretórios de forma semelhante à organização do namespace, assim fica fácil localizar uma classe na árvore de diretórios a partir do seu nome completo.
Acho que só faltou um detalhe importante no seu artigo, que é o tratamento sobre o autoload de classes. Com namespace é possível definir qual autoload cuida de qual namespace. Também é possível organizar as classes em diretórios de forma semelhante à organização do namespace, assim fica fácil localizar uma classe na árvore de diretórios a partir do seu nome completo.
08/12/2009 7:38pm
(~15 anos atrás)
Eu queria mesmo saber é como implementar um autoload para cada namespace, assim:
foo.php
bar.php
Eu sei que poderia ser usado o sql_autoload_register, mas isso já podia ser usado no PHP 5.2. Logo, ao meu ver, namespaces no PHP é meio inutil, uma vez que elas não definem padrões de autoload default como o Java ou Python.