CakeFest 2024: The Official CakePHP Conference

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 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. Será resolvido para diretorioatual/foo.txt onde diretorioatual é o diretório ocupado atualmente. Então, se o diretório atual for /home/foo, o nome será resolvido para /home/foo/foo.txt.
  2. Nome de caminho relativo como subdiretorio/foo.txt. Será resolvido para diretorioatual/subdiretorio/foo.txt.
  3. Nome de caminho absoluto como /main/foo.txt. Será resolvido para /main/foo.txt.
O mesmo princípio pode ser aplicado a elementos com namespace no PHP. Por exemplo, um nome de classe pode ser referenciado de 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 será resolvido para namespaceatual\foo. Se o código for global, sem namespace, ele será resolvido para foo. Uma ressalva: nomes não qualificados para funções e constantes serão resolvidos para funções e constantes globais se a função ou constante com namespace não for definida. Veja Usando namespaces: recorrendo a funções/constantes globais para obter detalhes.
  2. Nome qualificado ou um nome de classe prefixado como $a = new subnamespace\foo(); ou subnamespace\foo::metodoestatico();. Se o namespace atual for namespaceatual, ele será resolvido para namespaceatual\subnamespace\foo. Se o código for global, sem namespace, ele será resolvido para subnamespace\foo.
  3. Nome totalmente qualificado ou um nome prefixado com um operador de prefixo global como $a = new \namespaceatual\foo(); ou \namespaceatual\foo::metodoestatico();. Ele sempre será resolvido 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(); // será resolvido para a função Foo\Bar\foo
foo::metodoestatico(); // será resolvido para a classe Foo\Bar\foo, método metodoestatico
echo FOO; // será resolvido para a constante Foo\Bar\FOO

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

/* Nome totalmente qualificado */
\Foo\Bar\foo(); // será resolvido para a função Foo\Bar\foo
\Foo\Bar\foo::metodoestatico(); // será resolvido para a classe Foo\Bar\foo, método metodoestatico
echo \Foo\Bar\FOO; // será resolvido 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 em 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 um objeto da classe global Exception
?>

add a note

User Contributed Notes 5 notes

up
211
richard at richard-sumilang dot com
16 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
110
Anonymous
9 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
12 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
12 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
18
philip dot preisser at arcor dot de
12 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