PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Exceções> <Namespaces
Last updated: Fri, 22 Aug 2008

view this page in

Regras de resolução de nomes

Nomes são resolvidos seguindo estas regras de resolução:

  1. Todos nomes qualificados são traduzidos durante a compilação de acordo com a atual regra do import. Por exemplo, se o namespace A::B::C é importado, uma chamada para C::D::e() é traduzida para A::B::C::D::e().
  2. Nomes não qualificados de classes são traduzidos durante compilação de acordo com a atual regra de import (nome completo substituído pelo pequeno nome importado). Por exemplo, se o namespace A::B::C é importado, new C() é traduzido para new A::B::C().
  3. Dentro do namespace, chamadas para nomes não qualificados de funções que são definidos no atual namespace (e é conhecido na hora que a chamada é analisada) são interpretados como chamadas para estas funções do namespace, em tempo de compilação.
  4. Dentro do namespace (digo A::B), chamadas para funções não qualificadas que não são definidas no atual namespace são resolvidos em tempo de execução. Veja como uma chamada para uma função foo() é resolvida:
    1. Ele procura por uma função do atual namespace: A::B::foo().
    2. Ele procura e tenta chamar a função interna foo().
    Para chamar a função definida do usuário no namespace global, ::foo() tem que ser usado.
  5. Dentro do namespace (digo A::B), chamadas para não qualificados nomes de classes são resolvidos em tempo de execução. Veja como uma chamada para new C() é resolvida:
    1. Ele verifica por uma classe do namespace atual: A::B::C.
    2. Ele tenta buscar e chamar a classe interna C.
    3. Ele tenta fazer autoload A::B::C.
    Para referenciar a classe definida pelo usuário no namespace global, new ::C() tem que ser usado.
  6. Chamadas para qualificadas funções são resolvidas em tempo de execução. Veja como a chamada para A::B::foo() é resolvida:
    1. Ele verifica por uma função foo() no namespace A::B.
    2. Ele verifica por uma classe A::B e chama o método estático foo(). Irá fazer autoload da class se necessário.
  7. Qualificados nomes de classes são resolvidos em tempo de compilação como classes correspondentes do namespace. Por exemplo, new A::B::C() refere-se a classe C do namespace A::B.

Exemplo #1 Ilustrando resolução de nomes

<?php
namespace A
;

// function calls

foo();      // first tries to call "foo" defined in namespace "A"
            // then calls internal function "foo"

::foo();    // calls function "foo" defined in global scope

// class references

new B();    // first tries to create object of class "B" defined in namespace "A"
            // then creates object of internal class "B"

new ::B();  // creates object of class "B" defined in global scope

// static methods/namespace functions from another namespace

B::foo();   // first tries to call function "foo" from namespace "A::B"
            // then calls method "foo" of internal class "B"

::B::foo(); // first tries to call function "foo" from namespace "B"
            // then calls method "foo" of class "B" from global scope

// static methods/namespace functions of current namespace

A::foo();   // first tries to call function "foo" from namespace "A::A"
            // then tries to call method "foo" of class "A" from namespace "A"
            // then tries to call function "foo" from namespace "A"
            // then calls method "foo" of internal class "A" 

::A::foo(); // first tries to call function "foo" from namespace "A"
            // then calls method "foo" of class "A" from global scope
?>


Exceções> <Namespaces
Last updated: Fri, 22 Aug 2008
 
add a note add a note User Contributed Notes
Regras de resolução de nomes
Raphael
26-Mar-2008 07:01
Dennis' note is irrelevant as of today : with last 5.3 builds it is possible to use class names which coincide with PHP's internal class names within your namespaces. His example using PDO now works correctly.
Will
21-Feb-2008 12:08
Agreed.  Dennis is right on with this.  To add on, requiring each file that includes a namespace also defeats the purpose of namespacing.  It makes more sense if you have a repository for namespaces and just use those.

Example:

/some/path/to/namespaces/

<?php

use Some::Namespace;

// Test is withing Namespace.
$t = new Test();
// Test2 is not, so it checks includes, etc.
$t = new Test2();

?>
Dennis
04-Jan-2008 03:18
Sadly enough, the latest class name resolution rules render PHP namespaces quite useless. It is impossible to use class names which coincide with PHP's internal class names within your namespaces unless you _explicitly_ use them and alias them!

The worst thing is that PHP internal class names _always_ will take precedence over your class names. This means that you start developing a toolkit and take good care to use and alias your class names (eg, Exception or DateTime or PDO). You also create classes with names that don't have names that would conflict with PHP's internal classes. However, after you have done lots of work on your toolkit you find out that there's been another extension added to PHP and it has a class that coincides with your class name. Your code becomes useless.

A quick example:

<?php
/*
 * (PDO.php)
 */

namespace my::name::space;

class
PDO {}
?>

<?php
/*
 * (Test.php)
 */

namespace my:name::space;

class
Test {
  static function
doSmth() {
   
$pdo = new PDO();
  }
}
?>

and this code:

<?php
include('PDO.php');
include(
'Test.php');

use
my::name::space::Test;

Test::doSmth();
?>

This of course will emit a warning that PDO constructor expects at least one parameter (which is perfectly correct for PHP Data Objects). Now go to your php.ini and disable lines

extension=php_dll.php

or

extension=pdo.so

as well as all other PDO drivers. Now run the example and it will produce no warnings!

I have used PDO class name here as it can be easily disabled to demonstrate the problem. Now imagine that PDO was not an internal class and you were using it in your code for some time already. Suddenly an extension author choses to use this name. And all your code is broken. You will have to go into every file that references that class and explicitly use it with an alias and rename all occurences of this class name to an alias.

As to me this is too far from solving the name collision issues!

Exceções> <Namespaces
Last updated: Fri, 22 Aug 2008
 
 
show source | credits | sitemap | contact | advertising | mirror sites