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.

  1. Se eu não utilizo namespames, devo me importar com esta documentação?
  2. Como utilizar classes internas ou globais dentro de um namespace?
  3. Como utilizar classes, funções ou constantes em um namespace, dentro de seu próprio namespace?
  4. Como nomes como \meu\nome e \nome são resolvidos?
  5. Como nome como my\name é resolvido?
  6. Como nome de classe não qualificado como name é resolvido?
  7. 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.

  1. Os nomes de importação não deve entrar em conflito com classes definidas no mesmo arquivo.
  2. Namespaces alinhados não são permitidos.
  3. Nomes de namespace dinâmicos (identificadores entre aspas) deve escapar da barra invertida.
  4. Undefined Constants referenced using any backslash die with fatal error
  5. 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:

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
'outro.php';

use
outra\coisa as MinhaClasse;
$a = new MinhaClasse; // instancia a 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 exeplo causa um erro fatal de conflito de nomes porque MinhaClasse está definida no mesmo arquivo de instrução de uso.

<?php
namespace minha\coisa;
use
outra\coisa as MinhaClasse;
class
MinhaClasse {} // erro fatal: MinhaClasse está com conflito de instrução de importação
$a = new MinhaClasse;
?>

Namespaces alinhados não são permitidos.

PHP não permite alinhar namespaces

<?php
namespace minha\coisa {
namespace
alinhar {
class
foo {}
}
}
?>
No entanto, é fácil simular o namespace alinhados como:
<?php
namespace minha\coisa\alinhada {
class
foo {}
}
?>

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.
?>

add a note

User Contributed Notes 6 notes

up
15
manolachef at gmail dot com
10 years ago
There is a way to define a namespaced constant that is a special, built-in constant, using define function and setting the third parameter case_insensitive to false:

<?php
namespace foo;
define(__NAMESPACE__ . '\NULL', 10); // defines the constant NULL in the current namespace
var_dump(NULL); // will show 10
var_dump(null); // will show NULL
?>

  No need to specify the namespace in your call to define(), like it happens usually
<?php
namespace foo;
define(INI_ALL, 'bar'); // produces notice - Constant INI_ALL already defined. But:

define(__NAMESPACE__ . '\INI_ALL', 'bar'); // defines the constant INI_ALL in the current namespace
var_dump(INI_ALL); // will show string(3)"bar". Nothing unespected so far. But:

define('NULL', 10); // defines the constant NULL in the current namespace...
var_dump(NULL); // will show 10
var_dump(null); // will show NULL
?>

  If the parameter case_insensitive is set to true
<?php
namespace foo;
define (__NAMESPACE__ . '\NULL', 10, true); // produces notice - Constant null already defined
?>
up
7
shaun at slickdesign dot com dot au
6 years ago
When creating classes or calling static methods from within namespaces using variables, you need to keep in mind that they require the full namespace in order for the appropriate class to be used; you CANNOT use an alias or short name, even if it is called within the same namespace. Neglecting to take this into account can cause your code to use the wrong class, throw a fatal missing class exception, or throw errors or warnings.

In these cases, you can use the magic constant __NAMESPACE__, or specify the full namespace and class name directly. The function class_exists also requires the full namespace and class name, and can be used to ensure that a fatal error won't be thrown due to missing classes.

<?php

namespace Foo;
class
Bar {
    public static function
test() {
        return
get_called_class();
    }
}

namespace
Foo\Foo;
class
Bar extends \Foo\Bar {
}

var_dump( Bar::test() ); // string(11) "Foo\Foo\Bar"

$bar = 'Foo\Bar';
var_dump( $bar::test() ); // string(7) "Foo\Bar"

$bar = __NAMESPACE__ . '\Bar';
var_dump( $bar::test() ); // string(11) "Foo\Foo\Bar"

$bar = 'Bar';
var_dump( $bar::test() ); // FATAL ERROR: Class 'Bar' not found or Incorrect class \Bar used
up
3
teohad at NOSPAM dot gmail dot com
6 years ago
[Editor's note: that behavior is caused by a bug in PHP 7.0, which has been fixed as of PHP 7.0.7.]

Regarding the entry "Import names cannot conflict with classes defined in the same file".
- I found that since PHP 7.0 this is no longer the case.
In PHP 7.0 you can have a class with a name that matches an imported class (or namespace or both at the same time).

<?php
namespace ns1 {
  class
ns1 {
    public static function
write() {
      echo
"ns1\\ns1::write()\n";
    }
  }
}

namespace
ns1\ns1 {
  class
ns1c {
    public static function
write() {
      echo
"ns1\\ns1\\ns1c::write()\n";
    }
  }
}

namespace
ns2 {
  use
ns1\ns1 as ns1; // both a class in ns1, and a namespace ns1\ns1
   
  // the next class causes fatal error in php 5.6, not in 7.0
 
class ns1 {
    public static function
write() {
      echo
"ns2\\ns1::write()\n";
    }
  }
   
 
ns1::write(); // calls imported ns1\ns1::write()
 
ns1\ns1c::write(); // calls imported ns1\ns1\ns1c::write()
 
namespace\ns1::write(); // calls ns2\ns1::write()
}
?>
up
6
phpcoder
8 years ago
Regarding "Neither functions nor constants can be imported via the use statement." Actually you can do it in PHP 5.6+:

<?php

// importing a function (PHP 5.6+)
use function My\Full\functionName;

// aliasing a function (PHP 5.6+)
use function My\Full\functionName as func;

// importing a constant (PHP 5.6+)
use const My\Full\CONSTANT;
?>
up
0
theking2 at king dot ma
8 months ago
Just like class names currently namespaces are not case sensitive. So no errors will be shown here:

<?php declare(strict_types=1);
namespace
Foo;
class
Bar {
  public function
__construct() {
    echo
'Map constructed';
  }
}

$foobar = new \foo\bar();
up
-4
okaresz
9 years ago
To correct manolachef's answer: define() ALWAYS defines constants in the GLOBAL namespace.

As nl-x at bita dot nl states in the note at http://www.php.net/manual/en/function.define.php, the constant "NULL" can be defined with define() case-sensitively, but can only be retrieved with constant(), leaving the meaning of NULL uppercase keyword as the only value of the type null.
To Top