## Preguntas frecuentes: lo que debe saber sobre espacios de nombres

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

Esta FAQ se divide en dos secciones: las preguntas comunes, y los puntos particulares de la implementación, que pueden ser útiles para la comprensión global.

Primero, las preguntas comunes.

1. Si no utilizo espacios de nombres, ¿debo preocuparme por ellos?
2. ¿Cómo utilizar una clase global o interna desde un espacio de nombres?
3. ¿Cómo utilizar las clases de espacios de nombres, las funciones o las constantes en su propio espacio?
4. ¿Cómo se resuelve un nombre como `\mon\nom` o `\nom`?
5. ¿Cómo se resuelve un nombre como `mon\nom`?
6. ¿Cómo se resuelve un nombre de clase sin calificación, como `nom`?
7. ¿Cómo se resuelve una función sin calificación o una constante de nombre `nom`?

Aquí están los puntos particulares de la implementación, que pueden ser útiles para la comprensión global.

1. Los nombres importados no deben entrar en conflicto con las clases definidas en el mismo archivo
2. Los espacios de nombres anidados están prohibidos
3. Los nombres de espacios de nombres dinámicos deben proteger el backslash
4. Las constantes no definidas referenciadas con un backslash producen un error fatal
5. Imposible reemplazar constantes especiales como `null`, `true` o `false`

### Si no utilizo espacios de nombres, ¿debo preocuparme por ellos?

No, los espacios de nombres no afectan el código existente, de una manera u otra, ni el código que se producirá y que no utiliza espacios de nombres. Puede escribir esto si lo desea:

Ejemplo #1 Acceso a una clase global desde fuera de un espacio de nombres

    <?php
    $a = new \stdClass;
    print $a::class;

Es una funcionalidad equivalente a:

Ejemplo #2 Acceder a clases globales fuera de un espacio de nombres

    <?php
    $a = new stdClass;
    print $a::class;

### ¿Cómo utilizar una clase global o interna desde un espacio de nombres?

Ejemplo #3 Acceso a clases internas desde un espacio de nombres

    <?php
    namespace foo;
    $a = new \stdClass;
    print $a::class . "\n";

    function test(?\ArrayObject $parameter_type_example = null) {}

    $a = \FilesystemIterator::CURRENT_AS_FILEINFO;
    print $a . "\n";

    // extensión de una clase interna o global
    class MyException extends \Exception {}
    print MyException::class . "\n";

### ¿Cómo utilizar las clases de espacios de nombres, las funciones o las constantes en su propio espacio?

Ejemplo #4 Acceso a clases, funciones y constantes internas en un espacio de nombres

    <?php
    namespace foo;

    class MaClasse {}

    // uso de una clase en el espacio de nombres actual, como tipo de parámetro
    function test(?MaClasse $parameter_type_example = null) {}

    // otra manera de usar una clase en el espacio de nombres actual como tipo de parámetro
    function test2(?\foo\MaClasse $parameter_type_example = null) {}

    // extensión de una clase en el espacio de nombres actual
    class Extended extends MaClasse {}
    print Extended::class . "\n";

    // acceso a una función global
    $a = \strlen("test");
    print $a . "\n";

    // acceso a una constante global
    $b = \INI_ALL;
    print $b . "\n";

### ¿Cómo se resuelve un nombre como `\mon\nom` o `\nom`?

Los nombres que comienzan con `\` siempre se resuelven como son, por lo que `\mon\nom` es en realidad `mon\nom`, y `\Exception` es `Exception`.

Ejemplo #5 Nombres de espacios absolutos

    <?php
    namespace foo;
    $a = new \mon\nom(); // instancia la clase "mon\nom"
    echo \strlen('hi'); // llama a la función "strlen"
    $a = \INI_ALL; // $a recibe el valor de la constante "INI_ALL"

### ¿Cómo se resuelve un nombre como `mon\nom`?

Los nombres que contienen un backslash pero no comienzan con un backslash, como `mon\nom` pueden resolverse de dos maneras diferentes.

Si ha habido una instrucción de importación que hace un alias de `mon`, entonces el alias importado se aplica en lugar de `mon`, y el espacio de nombres se convierte en `mon\nom`.

De lo contrario, el espacio de nombres actual se agrega antes del camino de la clase `mon\nom`.

Ejemplo #6 Nombres calificados

    <?php
    namespace foo;
    use blah\blah as foo;

    $a = new mon\nom(); // instancia la clase "foo\mon\nom"
    foo\bar::name(); // llama al método estático "name" en la clase "blah\blah\bar"
    mon\bar(); // llama a la función "foo\mon\bar"
    $a = mon\BAR; // asigna a $a el valor de la constante "foo\mon\BAR"

### ¿Cómo se resuelve un nombre de clase sin calificación, como `nom`?

Los nombres de clases que no contienen backslash como `nom` pueden resolverse de dos maneras diferentes.

Si hay una instrucción de importación que define un alias para `nom`, entonces se aplica el alias.

De lo contrario, se utiliza el espacio de nombres actual y se prefiere a `nom`.

Ejemplo #7 Clases sin calificación

    <?php
    namespace foo;
    use blah\blah as foo;

    $a = new nom(); // instancia la clase "foo\nom"
    foo::nom(); // llama al método estático "nom" en la clase "blah\blah"

### ¿Cómo se resuelve una función sin calificación o una constante de nombre `nom`?

Las funciones y constantes que no tienen backslash en su nombre como `nom` se resuelven de dos maneras diferentes:

Primero, se prefiere el espacio de nombres actual a `nom`.

Luego, si la constante o función `nom` no existe en el espacio de nombres actual, se utiliza la versión global de la constante o la función `nom`.

Ejemplo #8 Funciones y constantes sin espacio de nombres

    <?php
    namespace foo;
    use blah\blah as foo;

    const FOO = 1;

    function mon() {
        print __FUNCTION__ . "\n";
    }
    function foo() {
        print __FUNCTION__ . "\n";
    }
    function sort(&$a)
    {
        \sort($a); // Llamada a la función global "sort"
        $a = array_flip($a);
        return $a;
    }

    mon(); // llama "foo\mon"
    print strlen('hi') . "\n"; // llama a la función global "strlen" ya que "foo\strlen" no existe
    $arr = array(1,3,2);
    $b = sort($arr); // llama a la función "foo\sort"
    var_dump($b);
    foo(); // llama a la función "foo\foo": la importación no se aplica

    $a = FOO; // asigna a $a el valor de la constante "foo\FOO": la importación no se aplica
    print $a;
    $b = INI_ALL; // asigna a $b el valor de la constante "INI_ALL"
    print $b;

### Los nombres importados no deben entrar en conflicto con las clases definidas en el mismo archivo

La siguiente combinación de scripts es válida:

file1.php

    <?php
    namespace mes\trucs;
    class MaClasse {}

another.php

    <?php
    namespace another;
    class untruc {}

file2.php

    <?php
    namespace mes\trucs;
    include 'file1.php';
    include 'another.php';

    use another\untruc as MaClasse;
    $a = new MaClasse; // instancia la clase "untruc" del espacio de nombres another

No hay conflicto de nombres, incluso si la clase `MaClasse` existe en el espacio de nombres `mes\trucs`, ya que la definición de MaClasse está en un archivo separado. Sin embargo, el siguiente ejemplo produce un error fatal debido a un conflicto de nombres, ya que MaClasse se define en el mismo archivo que la instrucción use.

    <?php
    namespace mes\trucs;
    use another\untruc as MaClasse;
    class MaClasse {} // error fatal: MaClasse está en conflicto con la instrucción de importación
    $a = new MaClasse;

### Los espacios de nombres anidados están prohibidos

PHP no permite anidar espacios de nombres.

    <?php
    namespace mes\trucs {
        namespace nested {
            class foo {}
        }
    }

Sin embargo, es fácil simular espacios de nombres anidados, como esto:

    <?php
    namespace mes\trucs\nested {
        class foo {}
    }

### Los nombres de espacios de nombres dinámicos deben proteger el backslash

Es muy importante darse cuenta de que, como los backslash se utilizan como caracteres de escape en las cadenas, siempre deben duplicarse para poder usarlos en una cadena. De lo contrario, existe el riesgo de uso inesperado:

Ejemplo #9 Peligros de usar espacios de nombres en una cadena

    <?php
    $a = "dangereux\nom"; // \n es una nueva línea en una cadena!
    $obj = new $a;

    $a = 'pas\vraiment\dangereux'; // ningún problema aquí
    $obj = new $a;

En una cadena de comillas dobles, la secuencia de escape es mucho más segura de usar, pero aún se recomienda proteger siempre los backslashs en una cadena que contiene un espacio de nombres.

### Constantes no definidas referenciadas con un backslash producen un error fatal

Cualquier constante no definida que no tenga calificador como `FOO` producirá una advertencia: PHP asumía que `FOO` era el valor de la constante. Cualquier constante, calificada parcialmente o totalmente, que contenga un backslash, producirá un error fatal si no está definida.

Ejemplo #10 Constantes no definidas

    <?php
    namespace bar;
    $a = FOO; // produce una advertencia: constante no definida "FOO", que toma el valor de "FOO";
    $a = \FOO; // error fatal, constante de espacio de nombres no definida FOO
    $a = Bar\FOO; // error fatal, constante de espacio de nombres no definida bar\Bar\FOO
    $a = \Bar\FOO; // error fatal, constante de espacio de nombres no definida Bar\FOO

### Imposible reemplazar constantes especiales como `null`, `true` o `false`

Cualquier intento en un espacio de nombres de reemplazar las constantes nativas o especiales, produce un error fatal.

Ejemplo #11 Constantes que no pueden ser redefinidas

    <?php
    namespace bar;
    const NULL = 0; // error fatal;
    const true = 'stupid'; // aún otro error fatal;
    // etc.

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open