Usando namespaces: Fundamentos

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

Antes de discutir o uso de namespaces, é importante entender como o PHP sabe qual elemento de namespace o seu código está solicitando. Uma analogia simples pode ser feita entre os namespaces do PHP e um sistema de arquivos. Existem três maneiras de acessar um arquivo em um sistema de arquivos:

  1. Nome de arquivo relativo como foo.txt. É resolvido para diretorioatual/foo.txt onde diretorioatual é o diretório ocupado atualmente. Então, se o diretório atual for /home/foo, o nome resolve para /home/foo/foo.txt.
  2. Nome de caminho relativo como subdiretorio/foo.txt. É resolvido para diretorioatual/subdiretorio/foo.txt.
  3. Nome de caminho absoluto como /main/foo.txt. É resolvido para /main/foo.txt.
O mesmo princípio pode ser aplicado para elementos com namespace no PHP. Por exemplo, um nome de classe pode ser referenciado em três maneiras:
  1. Nome não qualificado, ou nome de classe sem prefixo como $a = new foo(); ou foo::metodoestatico();. Se o namespace atual for namespaceatual, ele é resolvido para namespaceatual\foo. Se o código for global, sem namespace, ele é resolvido para foo. Uma ressalva: nomes não qualificados para funções e constantes resolverão para funções e constantes globais se a função ou constante com namespace não estiver definida. Veja Usando namespaces: fallback para função/constante global para detalhes.
  2. Nome qualificado, ou nome de classe prefixado como $a = new subnamespace\foo(); ou subnamespace\foo::metodoestatico();. Se o namespace atual for namespaceatual, ele resolve para namespaceatual\subnamespace\foo. Se o código for global, sem namespace, ele resolve para subnamespace\foo.
  3. Nome totalmente qualificado, ou nome prefixado com um operador de prefixo global como $a = new \namespaceatual\foo(); ou \namespaceatual\foo::metodoestatico();. Ele sempre resolve para o nome literal especificado no código, namespaceatual\foo.

Aqui está um exemplo dos três tipos de sintaxe em código real:

arquivo1.php

<?php
namespace Foo\Bar\subnamespace;

const
FOO = 1;
function
foo() {}
class
foo
{
static function
metodoestatico() {}
}
?>

arquivo2.php

<?php
namespace Foo\Bar;
include
'arquivo1.php';

const
FOO = 2;
function
foo() {}
class
foo
{
static function
metodoestatico() {}
}

/* Nome não qualificado */
foo(); // resolve para a função Foo\Bar\foo
foo::metodoestatico(); // resolve para a classe Foo\Bar\foo, método metodoestatico
echo FOO; // resolve para a constante Foo\Bar\FOO

/* Nome qualificado */
subnamespace\foo(); // resolve para a função Foo\Bar\subnamespace\foo
subnamespace\foo::metodoestatico(); // resolve para a classe Foo\Bar\subnamespace\foo,
// método metodoestatico
echo subnamespace\FOO; // resolve para a constante constant Foo\Bar\subnamespace\FOO

/* Nome totalmente qualificado */
\Foo\Bar\foo(); // resolve para a função Foo\Bar\foo
\Foo\Bar\foo::metodoestatico(); // resolve para a classe Foo\Bar\foo, método metodoestatico
echo \Foo\Bar\FOO; // resolve para a constante Foo\Bar\FOO
?>

Note que para acessar qualquer classe, função ou constante global, um nome totalmente qualificado pode ser usado, como \strlen() ou \Exception ou \INI_ALL.

Exemplo #1 Acessando classes, funções e constantes globais de dentro de um namespace

<?php
namespace Foo;

function
strlen() {}
const
INI_ALL = 3;
class
Exception {}

$a = \strlen('oi'); // chama a função global strlen
$b = \INI_ALL; // acessa a constante global INI_ALL
$c = new \Exception('erro'); // instancia a classe global Exception
?>

add a note

User Contributed Notes 5 notes

up
199
richard at richard-sumilang dot com
14 years ago
Syntax for extending classes in namespaces is still the same.

Lets call this Object.php:

<?php

namespace com\rsumilang\common;

class
Object{
  
// ... code ...
}

?>

And now lets create a class called String that extends object in String.php:

<?php

class String extends com\rsumilang\common\Object{
  
// ... code ...
}

?>

Now if you class String was defined in the same namespace as Object then you don't have to specify a full namespace path:

<?php

namespace com\rsumilang\common;

class
String extends Object
{
  
// ... code ...
}

?>

Lastly, you can also alias a namespace name to use a shorter name for the class you are extending incase your class is in seperate namespace:

<?php

namespace com\rsumilang\util;
use
com\rsumlang\common as Common;

class
String extends Common\Object
{
  
// ... code ...
}

?>

- Richard Sumilang
up
106
Anonymous
8 years ago
<?php

namespace Foo;

try {
   
// Something awful here
    // That will throw a new exception from SPL
}
catch (
Exception as $ex) {
   
// We will never get here
    // This is because we are catchin Foo\Exception
}
?>

Instead use fully qualified name for the exception to catch it

<?php

namespace Foo;

try {
   
// something awful here
    // That will throw a new exception from SPL
}
catch (\
Exception as $ex) {
   
// Now we can get here at last
}
?>
up
48
Lukas Z
11 years ago
Well variables inside namespaces do not override others since variables are never affected by namespace but always global:
"Although any valid PHP code can be contained within a namespace, only four types of code are affected by namespaces: classes, interfaces, functions and constants. "

Source: "Defining Namespaces"
http://www.php.net/manual/en/language.namespaces.definition.php
up
39
tom at tomwardrop dot com
11 years ago
It seems the file system analogy only goes so far. One thing that's missing that would be very useful is relative navigation up the namespace chain, e.g.

<?php
namespace MyProject {
   class
Person {}
}

namespace
MyProject\People {
    class
Adult extends ..\Person {}
}
?>

That would be really nice, especially if you had really deep namespaces. It would save you having to type out the full namespace just to reference a resource one level up.
up
16
philip dot preisser at arcor dot de
11 years ago
Working with variables can overwrite equal variables in other namespaces

<?php // php5 - package-version : 5.3.5-1ubuntu7.2

   
namespace
   
main
   
{}

    namespace
   
main\sub1
   
{
       
$data = 1;
    }

    namespace
   
main\sub2
   
{
        echo
$data;// 1
       
$data = 2;
    }

    namespace
   
main\sub1
   
{
        echo
$data;// 2
       
$data = 1;
    }

    namespace
    {
        echo
$data;// 1
   
}

?>
To Top