Reglas de resolución de nombres

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

En el marco de las reglas de resolución, hay varias definiciones importantes:

Definiciones para los espacios de nombres
nombre no calificado

Esto es un identificador que no contiene un separador de espacio de nombres. Por ejemplo: Foo

nombre calificado

Esto es un identificador que contiene un separador de espacio de nombres. Por ejemplo: Foo\Bar

Nombre absoluto

Esto es un identificador que comienza con un separador de espacio de nombres. Por ejemplo: \Foo\Bar. El espacio de nombres Foo también es un nombre absoluto.

Nombre relativo

Esto es un identificador que comienza con namespace, como namespace\Foo\Bar.

Los nombres se resuelven siguiendo las siguientes reglas:

  1. Los nombres absolutos siempre se traducen por los nombres sin el separador de namespace. Por ejemplo, \A\B se traduce por A\B.
  2. Todos los nombres que no son absolutos se traducen con el namespace reemplazado por el namespace actual. Si el nombre aparece en el namespace global, el prefijo namespace\ se elimina. Por ejemplo namespace\A en el namespace X\Y se traduce por X\Y\A. El mismo nombre en el namespace global se traduce por A.
  3. Para los nombres absolutos, el primer segmento se traduce de acuerdo con la class/namespace de la tabla de importación. Por ejemplo, si el namespace A\B\C se importa como C, el nombre C\D\E se traduce por A\B\C\D\E.
  4. Para los nombres absolutos, si ninguna regla de importación se aplica, el namespace actual se prefiere al nombre. Por ejemplo, el nombre C\D\E en el namespace A\B, se traduce por A\B\C\D\E.
  5. Para los nombres absolutos, el nombre se traduce en relación con la tabla de importación actual para el tipo de símbolo respectivo. Esto significa que un nombre que se asemeja a una clase se traduce de acuerdo con la tabla de importación de class/namespace, los nombres de funciones utilizando la tabla de importación de funciones, y las constantes utilizando la tabla de importación de constantes. Por ejemplo, después use A\B\C; un uso como new C() corresponde al nombre A\B\C(). De la misma manera, después use function A\B\foo; un uso como foo() corresponde al nombre A\B\foo.
  6. Para los nombres relativos, si ninguna regla se aplica, y que el nombre hace referencia a una clase, el namespace actual sirve de prefijo. Por ejemplo new C() en el namespace A\B corresponde al nombre A\B\C.
  7. para los nombres relativos, si ninguna regla se aplica, y que el nombre hace referencia a una función o una constante, y que el código está fuera del namespace global, el nombre se resuelve por la ejecución. Supongamos que el código está en el namespace A\B, aquí es cómo se resuelve una llamada a la función foo():
    1. Busca una función en el espacio de nombres actual: A\B\foo().
    2. Intenta encontrar y llamar a la función global foo().

Ejemplo #1 Ejemplos de resolución de espacios de nombres

<?php
namespace A;
use
B\D, C\E 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 y funciones de un 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 y funciones de espacio de nombres del espacio actual

A\B::foo(); // llama al método "foo" de la clase "B" del espacio de nombres "A\A"
// si la clase "A\A\B" no se encuentra, intenta la carga automática en la clase "A\A\B"

\A\B::foo(); // llama al método "foo" de la clase "B" del espacio de nombres "A"
// si la clase "A\B" no se encuentra, intenta la carga automática en la clase "A\B"
?>