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

search for in the

FAQ: cosas que se necesitan saber sobre los espacios de nombres> <Usar espacios de nombres: una alternativa a funciones/constantes globales
[edit] Last updated: Fri, 17 May 2013

view this page in

Reglas de resolución de nombres

(PHP 5 >= 5.3.0)

Aquí hay algunas definiciones importantes para los propósitos de estas reglas de resolución:

Definiciones de nombres de espacios de nombres
Nombre no cualificado

Es un identificador sin un separador de espacios de nombres, como Foo

Nombre cualificado

Es un identificador con un separador de espacios de nombres, como Foo\Bar

Nombre completamente cualificado

Es un identificador con un separador de espacios de nombres que comienza con un separador de espacios de nombres, como \Foo\Bar. namespace\Foo también es un nombre completamente cualificado.

Los nombres se resuelven siguiendo estas reglas de resolución:

  1. Las llamadas a clases, funciones o constantes completamente cualificadas se resuleven en tiempo de compilación. Por ejemplo new \A\B se resuelve con la clase A\B.
  2. Todos los nombres no cualificados y cualificados (no los completamente cualificados) se traducen durante la compilación según las reglas de importación actuales. Por ejemplo, si el espacio de nombres A\B\C se importa como C, una llamada a C\D\e() se traduce a A\B\C\D\e().
  3. Dentro de un espacio de nombres, todos los nombres cualificados no traducidos según la reglas de importación tienen añadido al inicio el espacio de nombres actual. Por ejemplo, si una llamada a C\D\e() se lleva a cabo dentro del espacio de nombres A\B, es traduce a A\B\C\D\e().
  4. Los nombres de clases no cualificados se traducen durante la compilación según las reglas de importación actuales (el nombre completo sustituido por el nombre abreviado importado). Por ejemplo, si el espacio de nombres A\B\C se importa como C, new C() se traduce a new A\B\C().
  5. Dentro de un espacio de nombres (digamos A\B), las llamdas a funciones no cualificadas se resuelven en tiempo de ejecución. Aquí se muestra cómo se resuelve una llamada a la función foo():
    1. Se busca una función desde el espacio de nombres actual: A\B\foo().
    2. Se intenta encontrar y llamar a la función global foo().
  6. Dentro de un espacio de nombres (digamos A\B), las llamadas a nombres de clases no cualificados o cualificados (no los completamente cualificados) se resuelve en tiempo de ejecución. Aquí se muestra cómo se resuelve una llamada a new C() o a new D\E(). Para new C():
    1. Se busca una clase desde el espacio de nombres actual: A\B\C.
    2. Se intenta autocargar A\B\C.
    Para new D\E():
    1. Se busca una clase añadiendo al inicio el espacio de nombres actual: A\B\D\E.
    2. Se intenta autocargar A\B\D\E.
    Para referenciar cualquier clase global en el espacio de nombres global, se debe usar su nombre completamente cualificado new \C().

Ejemplo #1 Las resoluciones de nombres ilustradas

<?php
namespace A;
use 
B\DC\as F;

// llamadas a funciones

foo();      // primero se intenta llamar a "foo" definida en el espacio de nombres "A"
            // después se llama a la función global "foo"

\foo();     // se llama a la función "foo" definidia en el ámbito global

mi\foo();   // se llama a la función "foo" definida en el espacio de nombres "A\mi"

F();        // primero se intenta llamar a "F" definida en el espacio de nombres "A"
            // después se llama a la función global "F"

// referecias a clases

new B();    // crea un objeto de la clase "B" definida en el espacio de nombres "A"
            // si no se encuentra, se intenta autocargar la clase "A\B"

new D();    // usando las reglas de importación, se crea un objeto de la clase "D" definida en el
            // espacio de nombres "B"
            // si no se encuentra, se intenta autocargar la clase "B\D"

new F();    // usando las reglas de importación, se crea un objeto de la clase "E" definida en el
            // espacio de nombres "C"
            // si no se encuentra, se intenta autocargar la clase "C\E"

new \B();   // crea un objeto de la clase "B" definida en el ámbito global
            // si no se encuentra, se intenta autocargar la clase "B"

new \D();   // crea un objeto de la clase "D" definida en el ámbito global
            // si no se encuentra, se intenta autocargar la clase "D"

new \F();   // crea un objeto de la clase "F" definida en el ámbito global
            // si no se encuentra, se intenta autocargar la clase "F"

// métodos estáticos/funciones de espacio de nombres desde otro espacio de nombres

B\foo();    // se llama a la función "foo" desde el espacio de nombres "A\B"

B::foo();   // se llama al método "foo" de la clase "B" definidia en el espacio de nombres "A"
            // si no se encuentra la clase "A\B", se intenta autocargar la clase "A\B"

D::foo();   // usando las reglas de importación, se llama al método "foo" de la clase "D"
            // definida en el espacio de nombres "B"
            // si no se encuentra la clase "B\D", se intenta autocargar la clase "B\D"

\B\foo();   // se llama a la función "foo" desde el espacio de nombres "B"

\B::foo();  // se llama al método "foo" de la clase "B" desde el ámbito global
            // si no es encuentra la clase "B", se intenta autocargar la clase "B"

// métodos estáticos/funciones de espacio de nombres del espacio de nombres actual

A\B::foo();   // se llama al método "foo" de la clase "B" desde el espacio de nombres "A\A"
              // si no se encuentra la clase "A\A\B", se intenta autocargar la clase "A\A\B"

\A\B::foo();  // se llama al método "foo" de la clase "B" desde el espacio de nombres "A"
              // si no se encuentra la clase "A\B", se intenta autocargar la clase "A\B"
?>


add a note add a note User Contributed Notes Reglas de resolución de nombres - [5 notes]
up
1
kdimi
2 years ago
If you like to declare an __autoload function within a namespace or class, use the spl_autoload_register() function to register it and it will work fine.
up
3
rangel
3 years ago
The term "autoload" mentioned here shall not be confused with __autoload function to autoload objects. Regarding the __autoload and namespaces' resolution I'd like to share the following experience:

->Say you have the following directory structure:

- root
      | - loader.php
      | - ns
             | - foo.php

->foo.php

<?php
namespace ns;
class
foo
{
    public
$say;
   
    public function
__construct()
    {
       
$this->say = "bar";
    }
   
}
?>

-> loader.php

<?php
//GLOBAL SPACE <--
function __autoload($c)
{
    require_once
$c . ".php";
}

class
foo extends ns\foo // ns\foo is loaded here
{
    public function
__construct()
    {
       
parent::__construct();
        echo
"<br />foo" . $this->say;
    }
}
$a = new ns\foo(); // ns\foo also loads ns/foo.php just fine here.
echo $a->say;   // prints bar as expected.
$b = new foo// prints foobar just fine.
?>

If you keep your directory/file matching namespace/class consistence the object __autoload works fine.
But... if you try to give loader.php a namespace you'll obviously get fatal errors.
My sample is just 1 level dir, but I've tested with a very complex and deeper structure. Hope anybody finds this useful.

Cheers!
up
0
rangel
3 years ago
The term "autoload" mentioned here shall not be confused with __autoload function to autoload objects. Regarding the __autoload and namespaces' resolution I'd like to share the following experience:

->Say you have the following directory structure:

- root
      | - loader.php
      | - ns
             | - foo.php

->foo.php

<?php
namespace ns;
class
foo
{
    public
$say;
   
    public function
__construct()
    {
       
$this->say = "bar";
    }
   
}
?>

-> loader.php

<?php
//GLOBAL SPACE <--
function __autoload($c)
{
    require_once
$c . ".php";
}

class
foo extends ns\foo // ns\foo is loaded here
{
    public function
__construct()
    {
       
parent::__construct();
        echo
"<br />foo" . $this->say;
    }
}
$a = new ns\foo(); // ns\foo also loads ns/foo.php just fine here.
echo $a->say;   // prints bar as expected.
$b = new foo// prints foobar just fine.
?>

If you keep your directory/file matching namespace/class consistence the object __autoload works fine.
But... if you try to give loader.php a namespace you'll obviously get fatal errors.
My sample is just 1 level dir, but I've tested with a very complex and deeper structure. Hope anybody finds this useful.

Cheers!
up
0
safakozpinar at NOSPAM dot gmail dot com
2 years ago
As working with namespaces and using (custom or basic) autoload structure; magic function __autoload must be defined in global scope, not in a namespace, also not in another function or method.

<?php
namespace Glue {
   
/**
     * Define your custom structure and algorithms
     * for autoloading in this class.
     */
   
class Import
   
{
        public static function
load ($classname)
        {
            echo
'Autoloading class '.$classname."\n";
            require_once
$classname.'.php';
        }
    }
}

/**
 * Define function __autoload in global namespace.
 */
namespace {
   
    function
__autoload ($classname)
    {
        \
Glue\Import::load($classname);
    }

}
?>
up
0
sammaye
2 years ago
I have noticed one problem with __autoload function. Say you have two namespaces, one is a sub of the other:

\Glue
\Glue\Import

Within that Import namespace you have a function auto() with the magic __autoload inside. No matter what you do that auto() will never traverse it's sub function meaning you will nevber get an __autoload function.

Even if you put the __autoload within a class within the namespace as such:

<?php
namespace Glue\Import;

class
import{
    private static
$_AutoLoad = array();
    private static
$_Imported = array();

    function
load($sName){
        if(! isset(
self::$_AutoLoad[$sName]))
           
//throw new ImportError("Cannot import module with name '$sName'.");
           
echo("file with name '$sName' failed to load with path '".self::$_AutoLoad[$sName]."'");
        if(! isset(
self::$_Imported[$sName])){
           
self::$_Imported[$sName] = True;
            return include_once(
self::$_AutoLoad[$sName]);       
        }
    }
   
    function
push($sName, $sPath){
       
self::$_AutoLoad[$sName] = $sPath;
    }
   
    function
auto(){
        function
__autoload($sClass){
           
load($sClass);
        }
    }
}
?>

It will not work. Just something to keep in mind.

 
show source | credits | sitemap | contact | advertising | mirror sites