(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Estas perguntas frequentes são divididas em duas seções: perguntas comuns e alguns detalhes de implementação úteis para entender os pormenores.
Primeiro, as perguntas comuns.
\meu\nome
ou \nome
são resolvidos? meu\nome
é resolvido?nome
é resolvido?nome
é resolvido?Há alguns detalhes de implementação dos namespaces úteis para entendê-los melhor.
null
, true
ou false
Não. Namespaces não afetam nenhum código existente de forma alguma, ou qualquer código ainda a ser escrito que não contenha namespaces. Você pode escrever este código se desejar:
Exemplo #1 Acessando classes globais fora de um namespace
<?php
$a = new \stdClass;
?>
O exemplo acima é equivalente ao seguinte código:
Exemplo #2 Acessando classes globais fora de um namespace
<?php
$a = new stdClass;
?>
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;
// estendendo uma classe interna ou global
class MinhaExcecao extends \Exception {}
?>
Exemplo #4 Acessando classes, funções ou constantes internas em namespaces
<?php
namespace foo;
class MinhaClasse {}
// usando uma classe do namespace atual como tipo de parâmetro
function test(MinhaClasse $exemplo_com_tipo_de_parametro = null) {}
// outra forma de usar a classe do namespace atual como tipo de parâmetro
function test(\foo\MinhaClasse $exemplo_com_tipo_de_parametro = null) {}
// estendendo uma classe do namespace atual
class Estendida extends MinhaClasse {}
// acessando uma função global
$a = \funcao_global();
// acessando uma constante global
$b = \INI_ALL;
?>
\meu\nome
ou \nome
são resolvidos? Nomes que começam com uma barra invertida (\
) sempre são resolvidos 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
<?php
namespace foo;
$a = new \meu\nome(); // instancia um objeto da classe "meu\nome"
echo \strlen('olá'); // invoca a função "strlen"
$a = \INI_ALL; // define $a com o valor da constante "INI_ALL"
?>
meu\nome
é resolvido? Nomes que contêm barra invertida, mas não começam com uma barra invertida, como meu\nome
podem ser resolvidos de duas maneiras diferentes.
Se houver uma instrução de importação que cria o apelido meu
para outro nome, então o apelido da importação será aplicado ao meu
em meu\nome
.
Caso contrário, o nome do namespace atual será prefixado a meu\nome
.
Exemplo #6 Nomes qualificados
<?php
namespace foo;
use bla\bla as foo;
$a = new meu\nome(); // instancia um objeto da classe "foo\meu\nome"
foo\bar::nome(); // chama o método estático "nome" na classe "bla\bla\bar"
minha\bar(); // chama a função "foo\minha\bar"
$a = minha\BAR; // define $a com o valor da constante "foo\minha\BAR"
?>
nome
é resolvido? Nomes de classes que não contêm barra invertida como nome
podem ser resolvidos de duas maneiras diferentes.
Se houver uma instrução de importação que cria o apelido nome
para outro nome, então o apelido da importação será aplicado.
Caso contrário, o nome do namespace atual será prefixado a nome
.
Exemplo #7 Nomes de classe não qualificados
<?php
namespace foo;
use bla\bla as foo;
$a = new nome(); // instancia um objeto da classe "foo\nome"
foo::nome(); // chama o método estático "nome" na classe "bla\bla"
?>
nome
é resolvido? Nomes de funções ou constantes que não contêm barra invertida como nome
podem ser resolvidos de duas maneiras diferentes.
Primeiro, o nome do namespace atual será prefixado a nome
.
Finalmente, se a contante ou função nome
não existir no namespace atual, uma constante ou função global nome
será usada se existir.
Exemplo #8 Nomes de funções ou constantes não qualificados
<?php
namespace foo;
use bla\bla as foo;
const FOO = 1;
function minha() {}
function foo() {}
function sort(&$a)
{
\sort($a); // chama a função global "sort"
$a = array_flip($a);
return $a;
}
minha(); // chama "foo\minha"
$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" - a importação não é aplicada
$a = FOO; // define $a com o valor da constante "foo\FOO" - a importação não é aplicada
$b = INI_ALL; // define $b com o valor da constante global "INI_ALL"
?>
As seguintes combinações de script são válidas:
arquivo1.php
<?php
namespace minha\coisa;
class MinhaClasse {}
?>
outra.php
<?php
namespace outra;
class coisa {}
?>
arquivo2.php
<?php
namespace minha\coisa;
include 'arquivo1.php';
include 'outra.php';
use outra\coisa as MinhaClasse;
$a = new MinhaClasse; // instancia um objeto da classe coisa do namespace outra
?>
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 exemplo causa um erro fatal de conflito de nomes porque MinhaClasse está definida no mesmo arquivo que a declaração use.
<?php
namespace minha\coisa;
use outra\coisa as MinhaClasse;
class MinhaClasse {} // erro fatal: MinhaClasse está em conflito com a declaração de importação
$a = new MinhaClasse;
?>
O PHP não permite aninhar namespaces.
<?php
namespace minha\coisa {
namespace aninhada {
class foo {}
}
}
?>
<?php
namespace minha\coisa\aninhada {
class foo {}
}
?>
É muito importante perceber que, como a barra invertida é usada como um caractere de escape dentro de strings, ela sempre deve ser duplicada quando usada em uma string. Caso contrário, existe o risco de consequências não desejadas:
Exemplo #9 Perigos do uso de nomes com namespace em uma string com aspas duplas
<?php
$a = "\nome\perigoso"; // \n é uma nova linha dentro de strings com aspas duplas!
$obj = new $a;
$a = 'nada\perigoso'; // não há problemas aqui.
$obj = new $a;
?>
Qualquer constante indefinida não qualificada como FOO
gerará um alerta explicando que o PHP assumiu que FOO
era o valor da constante. Qualquer constante, qualificada ou totalmente qualificada, que contenha uma barra invertida produzirá um erro fatal se não for encontrada.
Exemplo #10 Constantes não definidas
<?php
namespace bar;
$a = FOO; // Produz um alerta - constante indefinida FOO assumiu "FOO"
$a = \FOO; // Erro fatal, constante de namespace indefinida FOO
$a = Bar\FOO; // Erro fatal, constante de namespace indefinida bar\Bar\FOO
$a = \Bar\FOO; // Erro fatal, constante de namespace indefinida Bar\FOO
?>
null
, true
ou false
Qualquer tentativa de definir uma constante de namespace que seja uma constante especial nativa resultará em um erro fatal.
Exemplo #11 Constantes não definidas
<?php
namespace bar;
const NULL = 0; // Erro fatal
const true = 'verdadeiro'; // Também um erro fatal
// etc.
?>