Perguntas Frequentes (FAQ): Coisas que você precisa saber sobre namespaces
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Este FAQ se divide em duas seções: perguntas comuns e alguns detalhes de
implementação úteis de se entender completamente.
Primeiro, as perguntas comuns.
-
Se eu não utilizo namespames, devo me importar
com esta documentação?
-
Como utilizar classes internas ou globais
dentro de um namespace?
-
Como utilizar classes,
funções ou constantes em um namespace, dentro de seu próprio namespace?
-
Como nomes como
\meu\nome
e \nome
são resolvidos?
-
Como nome como
my\name
é resolvido?
-
Como nome de classe não qualificado
como
name
é resolvido?
-
Como nome de função
não qualificada ou nome de constante não qualificada
como
name
é resolvido?
Há alguns detalhes de implementação dos namespaces que são úteis de se
entender.
-
Os nomes de importação não deve entrar em conflito com
classes definidas no mesmo arquivo.
-
Namespaces alinhados não são permitidos.
-
Nomes de namespace dinâmicos (identificadores
entre aspas) deve escapar da barra invertida.
-
Undefined Constants referenced
using any backslash die with fatal error
-
Cannot override special
constants NULL, TRUE, FALSE, ZEND_THREAD_SAFE or ZEND_DEBUG_BUILD
Se eu não utilizo namespames, devo me importar com esta documentação?
Não. Namespaces não afetam nenhum código que já exista, ou que venha
a existir, que não contenha namespaces. Você pode escrever o seguinte se
quiser:
Exemplo #1 Acessando classes glboais fora de um namespace
<?php
$a = new \stdClass;
?>
O exemplo acima é equivalente ao seguinte código:
Exemplo #2 Accessing global classes outside a namespace
<?php
$a = new stdClass;
?>
Como utilizar classes internas ou globais dentro de um namespace?
Exemplo #3 Acessando classes internas em namespaces
<?php
namespace foo;
$a = new \stdClass;
function test(\ArrayObject $exemplo_com_tipo_de_parametro = null) {}
$a = \DirectoryIterator::CURRENT_AS_FILEINFO;
// herança de uma classe interna ou global
class MyException extends \Exception {}
?>
Como utilizar classes, funções ou constantes em um namespace, dentro de seu próprio
namespace?
Exemplo #4 Acessando classes, funções ou constantes internas em um namespace
<?php
namespace foo;
class MinhaClasse {}
// utilizando uma classe do namespace atual como tipo de parâmetro
function test(MinhaClasse $exemplo_com_tipo_de_parametro = null) {}
// outra forma de utilizar a classe do namespace atual como tipo de parâmetro
function test(\foo\MinhaClasse $exemplo_com_tipo_de_parametro = null) {}
// herança de classe a partir do namespace atual
class Extended extends MyClass {}
// acessando uma função global
$a = \globalfunc();
// acessando uma constante global
$b = \INI_ALL;
?>
Como nomes como \meu\nome
e \nome
são resolvidos?
Nomes que começam com uma barra invertida (\
) sempre resolvem
para seu conteúdo exato. Então \meu\nome
é o mesmo que meu\nome
,
e \Exception
é o mesmo que Exception
.
Exemplo #5 Nomes totalmente qualificados (FQN)
<?php
namespace foo;
$a = new \meu\nome(); // cria uma instância da classe "meu\nome"
echo \strlen('olá'); // invoca a função "strlen"
$a = \INI_ALL; // $a recebe o valor da constante "INI_ALL"
?>
Como nome como my\name
é resolvido?
Nomes que contêm uma barra invertida, mas não começam com uma barra invertida como
my\name
podem ser resolvidos de 2 maneiras diferentes.
Se houver
uma instrução de importação que apelide outro nome a my
, então
o apelido de importação será aplicado ao my
em my\name
.
Caso contrário, o nome do namespace atual será anexado a my\name
.
Exemplo #6 Nomes qualificados
<?php
namespace foo;
use blah\blah as foo;
$a = new my\name(); // instancia a classe "foo\my\name"
foo\bar::name(); // chama método estátido "name" na classe "blah\blah\bar"
my\bar(); // chama a função "foo\my\bar"
$a = my\BAR; // define $a com o valor da constante "foo\my\BAR"
?>
Como nome de classe não qualificado como name
é resolvido?
Nomes de classes que não contêm barra invertida como
name
pode ser resolvidos de 2 maneiras diferentes.
Se houver
uma instrução de importação que apelide outro nome a name
, então
o apelido de importação será aplicado.
Caso contrário, o nome do namespace atual será anexado a name
.
Exemplo #7 Nomes de classes não qualificados
<?php
namespace foo;
use blah\blah as foo;
$a = new name(); // instância a classe "foo\name"
foo::name(); // chama o método estático "name" na classe "blah\blah"
?>
Como nome de função não qualificada ou nome de constânte não qualificada
como name
é resolvido?
Nomes de funções ou constântes que não contêm barra invertida como
name
pode ser resolvidos de 2 maneiras diferentes.
Primeito, o nome do namespace atual será anexado a name
.
Finalmente, se a contante ou função name
não existir
no namespace atual, uma constante ou função global name
será usada se existir.
Exemplo #8 Nomes de funções ou constante não qualificadas
<?php
namespace foo;
use blah\blah as foo;
const FOO = 1;
function my() {}
function foo() {}
function sort(&$a)
{
\sort($a); // chama a função global "sort"
$a = array_flip($a);
return $a;
}
my(); // chama "foo\my"
$a = strlen('hi'); // chama a função global "strlen" porque não existe "foo\strlen"
$arr = array(1,3,2);
$b = sort($arr); // chama a função "foo\sort"
$c = foo(); // chama a função "foo\foo" - importação não é aplicada
$a = FOO; // define $a com o valor da constante "foo\FOO" - importação não é aplicada
$b = INI_ALL; // define $b com o valor da constante global "INI_ALL"
?>
Os nomes de importação não devem entrar em conflito com classes definidas no mesmo arquivo.
As seguintes combinação de script são válidas:
Não há conflito de nomes, mesmo que a classe MinhaClasse
exista
dentro do namespace minha\coisa
, porque a definição de MinhaClasse está
em um arquivo separado. No entanto, o próximo exeplo causa um erro fatal de conflito de nomes
porque MinhaClasse está definida no mesmo arquivo de instrução de uso.
Namespaces alinhados não são permitidos.
PHP não permite alinhar namespaces
No entanto, é fácil simular o namespace alinhados como:
Nomes de namespace dinâmicos (identificadores entre aspas) deve escapar da barra invertida
É muito importante perceber o porque a barra invertida é usada para escapar caracter
dentro de strings,isso deve sempre ser duplicado quando usado em uma sitrng. Por outro lado,
existe um risco de consequências não desejadas.
Exemplo #9 Perigo de usar nomes com namespace dentro de uma string com aspas duplas
<?php
$a = "dangerous\name"; // \n é uma nova linha dentro da string de aspas duplas!
$obj = new $a;
$a = 'not\at\all\dangerous'; // não a problemas aqui.
$obj = new $a;
?>
Dentro de string com aspas simples, a sequência de escape de barra invertida é muito mais segura de usar, mas
ainda é recomendado como boa prática escapar com barras invertidas em todas as springs.
Constantes indefinidas referenciadas por contrabarra geram erro fatal
Quaisquer constantes não qualificadas como por exemplo FOO
geram
um alerta avisando que o PHP assumirá que FOO
era o valor
da constante. Quaisquer constantes, qualificadas ou totalmente qualificadas, que portanto
contém uma contrabarra, gerará um erro fatal se não definida.
Exemplo #10 Constantes qualificadas não definidas
<?php
namespace bar;
$a = FOO; // Produz um alerta - constante FOO assume o valor "FOO"
$a = \FOO; // Erro fatal, constante qualificada indefinida FOO
$a = Bar\FOO; // Erro fatal, constante qualificada indefinida bar\Bar\FOO
$a = \Bar\FOO; // Erro fatal, constante qualificada indefinida Bar\FOO
?>
Impossibilidade de sobrescrever constantes especiais NULL, TRUE, FALSE, ZEND_THREAD_SAFE ou ZEND_DEBUG_BUILD
Quaisquer tentativas de definir uma constante que seja especial, mesmo que dentro de namespaces,
resultam em um erro fatal.
Exemplo #11 Constantes não definíveis
<?php
namespace bar;
const NULL = 0; // Erro fatal
const true = 'stupid'; // Também um erro fatal
// etc.
?>