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

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

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

Primero, las preguntas frecuentes.

  1. Si no se utilizan 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?

A continuación se muestran 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 fichero
  2. Los espacios de nombres anidados están prohibidos
  3. Los nombres de espacios de nombres dinámicos deben proteger el antislash
  4. Las constantes indefinidas referenciadas con un antislash producen un error fatal
  5. Imposible reemplazar constantes especiales como null, true o false

Si no se utilizan 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 los espacios de nombres. Se puede escribir esto si se desea:

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

<?php
$a
= new \stdClass;
?>

Es una funcionalidad equivalente a:

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

<?php
$a
= new stdClass;
?>

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

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

<?php
namespace foo;
$a = new \stdClass;

function
probar(\ArrayObject $ejemploalusiónatipo = null) {}

$a = \DirectoryIterator::CURRENT_AS_FILEINFO;

// extender una clase interna o global
class MiExcepción extends \Exception {}
?>

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

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

<?php
namespace foo;

class
MiClase {}

// usar una clase desde el espacio de nombres actual como una declaración de tipo
function probar(MiClase $ejemploalusiónatipo = null) {}
// otra manera de usar una clase desde el espacio de nombres actual una declaración de tipo
function probar(\foo\MiClase $ejemploalusiónatipo = null) {}

// extender una clase desde el espacio de nombres actual
class Extendida extends MiClase {}

// acceder a una función global
$a = \funcglobal();

// acceder a una constante global
$b = \INI_ALL;
?>

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

Los nombres que comienzan con \ siempre se resuelven en lo que parecen, 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 \mi\nombre(); // instancia a la clase "mi\nombre"
echo \strlen('hola'); // llama a la función "strlen"
$a = \INI_ALL; // $a está establecida al valor de la constante "INI_ALL"
?>

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

Los nombres que contienen un antislash pero no comienzan con un antislash, como mon\nom pueden ser resueltos 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 añade antes del camino de la clase mon\nom.

Ejemplo #6 Nombres calificados

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

$a = new mi\nombre(); // instancia a la clase "foo\mi\nombre"
foo\bar::nombre(); // llama a método estático "nombre" de la clase "blah\blah\bar"
mi\bar(); // llama a la función "foo\mi\bar"
$a = mi\BAR; // establece $a al valor de la constante "foo\mi\BAR"
?>

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

Los nombres de clases que no contienen un antislash como nom pueden ser resueltos de dos maneras diferentes.

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

De lo contrario, el espacio de nombres actual se utiliza 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 un antislash en su nombre como nom se resuelven de dos maneras diferentes:

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

Luego, si la constante o la 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
mi() {}
function
foo() {}
function
sort(&$a)
{
\sort($a); // invoca a la función global "sort"
$a = array_flip($a);
return
$a;
}

mi(); // calls "foo\mi"
$a = strlen('hola'); // llama a la función global "strlen" ya que "foo\strlen" no existe
$array = array(1,3,2);
$b = sort($array); // llama a la función "foo\sort"
$c = foo(); // llama a la función "foo\foo" - la importación no se aplica

$a = FOO; // establece $a al valor de la constante "foo\FOO"; la importación no se aplica
$b = INI_ALL; // establece $b al valor de la constante "INI_ALL"
?>

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

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

file1.php

<?php
namespace mis\cosas;
class
MiClase {}
?>

another.php

<?php
namespace otro;
class
cosa {}
?>

file2.php

<?php
namespace mis\cosas;
include
'fichero1.php';
include
'otro.php';

use
otro\cosa as MiClase;
$a = new MiClase; // instancia a la clase "cosa" del espacio de nombres otro
?>

No hay conflicto de nombres, aunque la clase MiClase existe en el espacio de nombres mes\trucs, ya que la definición de MiClase está en un fichero separado. Sin embargo, el ejemplo siguiente produce un error fatal debido a un conflicto de nombres, ya que MiClase está definida en el mismo fichero que la instrucción use.

<?php
namespace mis\cosas;
use
otro\cosa as MiClase;
class
MiClase {} // error fatal: MiClase entra en conflicto con la sentencia de importación
$a = new MiClase;
?>

Los espacios de nombres anidados están prohibidos

PHP no permite anidar espacios de nombres.

<?php
namespace mis\cosas {
namespace
anidado {
class
foo {}
}
}
?>
Sin embargo, es fácil simular espacios de nombres anidados, como esto:
<?php
namespace mis\cosas\anidado {
class
foo {}
}
?>

Los nombres de espacios de nombres dinámicos deben proteger el antislash

Es muy importante tener en cuenta que, como los antislash se utilizan como caracteres de protección en las cadenas, siempre deben ser duplicados para poder ser utilizados en una cadena. De lo contrario, existe el riesgo de uso inesperado:

Ejemplo #9 Peligros del uso de los espacios de nombres en una cadena

<?php
$a
= "peligroso\nombre"; // ¡\n es una nueva línea dentro de las cadenas entre comillas dobles!
$obj = new $a;

$a = 'sin\peligro\alguno'; // aquí sin problemas.
$obj = new $a;
?>
En una cadena con comillas dobles, la secuencia de protección es mucho más segura de usar, pero aún así se recomienda proteger siempre los antislashs en una cadena que contiene un espacio de nombres.

Las constantes indefinidas referenciadas con un antislash producen un error fatal

Toda constante indefinida que no esté calificada, como FOO producirá una advertencia: PHP suponía que FOO era el valor de la constante. Toda constante, calificada parcialmente o totalmente, que contenga un antislash, producirá un error fatal si está indefinida.

Ejemplo #10 Constantes indefinidas

<?php
namespace bar;
$a = FOO; // produce un aviso - constante no definida "FOO" se asume que es "FOO";
$a = \FOO; // error fatal, constante FOO del espacio de nombres no definida
$a = Bar\FOO; // error fatal, constante bar\Bar\FOO del espacio de nombres no definida
$a = \Bar\FOO; // error fatal, constante Bar\FOO del espacio de nombres no definida
?>

Imposible reemplazar constantes especiales como null, true o false

Todo 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 = 'estúpido'; // también error fatal;
// etc.
?>

add a note

User Contributed Notes 6 notes

up
15
manolachef at gmail dot com
13 years ago
There is a way to define a namespaced constant that is a special, built-in constant, using define function and setting the third parameter case_insensitive to false:

<?php
namespace foo;
define(__NAMESPACE__ . '\NULL', 10); // defines the constant NULL in the current namespace
var_dump(NULL); // will show 10
var_dump(null); // will show NULL
?>

No need to specify the namespace in your call to define(), like it happens usually
<?php
namespace foo;
define(INI_ALL, 'bar'); // produces notice - Constant INI_ALL already defined. But:

define(__NAMESPACE__ . '\INI_ALL', 'bar'); // defines the constant INI_ALL in the current namespace
var_dump(INI_ALL); // will show string(3)"bar". Nothing unespected so far. But:

define('NULL', 10); // defines the constant NULL in the current namespace...
var_dump(NULL); // will show 10
var_dump(null); // will show NULL
?>

If the parameter case_insensitive is set to true
<?php
namespace foo;
define (__NAMESPACE__ . '\NULL', 10, true); // produces notice - Constant null already defined
?>
up
7
shaun at slickdesign dot com dot au
8 years ago
When creating classes or calling static methods from within namespaces using variables, you need to keep in mind that they require the full namespace in order for the appropriate class to be used; you CANNOT use an alias or short name, even if it is called within the same namespace. Neglecting to take this into account can cause your code to use the wrong class, throw a fatal missing class exception, or throw errors or warnings.

In these cases, you can use the magic constant __NAMESPACE__, or specify the full namespace and class name directly. The function class_exists also requires the full namespace and class name, and can be used to ensure that a fatal error won't be thrown due to missing classes.

<?php

namespace Foo;
class
Bar {
public static function
test() {
return
get_called_class();
}
}

namespace
Foo\Foo;
class
Bar extends \Foo\Bar {
}

var_dump( Bar::test() ); // string(11) "Foo\Foo\Bar"

$bar = 'Foo\Bar';
var_dump( $bar::test() ); // string(7) "Foo\Bar"

$bar = __NAMESPACE__ . '\Bar';
var_dump( $bar::test() ); // string(11) "Foo\Foo\Bar"

$bar = 'Bar';
var_dump( $bar::test() ); // FATAL ERROR: Class 'Bar' not found or Incorrect class \Bar used
up
3
theking2 at king dot ma
2 years ago
Just like class names currently namespaces are not case sensitive. So no errors will be shown here:

<?php declare(strict_types=1);
namespace
Foo;
class
Bar {
public function
__construct() {
echo
'Map constructed';
}
}

$foobar = new \foo\bar();
up
3
teohad at NOSPAM dot gmail dot com
9 years ago
[Editor's note: that behavior is caused by a bug in PHP 7.0, which has been fixed as of PHP 7.0.7.]

Regarding the entry "Import names cannot conflict with classes defined in the same file".
- I found that since PHP 7.0 this is no longer the case.
In PHP 7.0 you can have a class with a name that matches an imported class (or namespace or both at the same time).

<?php
namespace ns1 {
class
ns1 {
public static function
write() {
echo
"ns1\\ns1::write()\n";
}
}
}

namespace
ns1\ns1 {
class
ns1c {
public static function
write() {
echo
"ns1\\ns1\\ns1c::write()\n";
}
}
}

namespace
ns2 {
use
ns1\ns1 as ns1; // both a class in ns1, and a namespace ns1\ns1

// the next class causes fatal error in php 5.6, not in 7.0
class ns1 {
public static function
write() {
echo
"ns2\\ns1::write()\n";
}
}

ns1::write(); // calls imported ns1\ns1::write()
ns1\ns1c::write(); // calls imported ns1\ns1\ns1c::write()
namespace\ns1::write(); // calls ns2\ns1::write()
}
?>
up
7
phpcoder
10 years ago
Regarding "Neither functions nor constants can be imported via the use statement." Actually you can do it in PHP 5.6+:

<?php

// importing a function (PHP 5.6+)
use function My\Full\functionName;

// aliasing a function (PHP 5.6+)
use function My\Full\functionName as func;

// importing a constant (PHP 5.6+)
use const My\Full\CONSTANT;
?>
up
-5
okaresz
11 years ago
To correct manolachef's answer: define() ALWAYS defines constants in the GLOBAL namespace.

As nl-x at bita dot nl states in the note at http://www.php.net/manual/en/function.define.php, the constant "NULL" can be defined with define() case-sensitively, but can only be retrieved with constant(), leaving the meaning of NULL uppercase keyword as the only value of the type null.
To Top