Los espacios de nombres Introducción a los espacios de nombres Introducción ¿Qué son los espacios de nombres? En su definición más amplia, representan un medio para encapsular elementos. Esto puede concebirse como un concepto abstracto, por varias razones. Por ejemplo, en un sistema de archivos, los directorios representan un grupo de archivos asociados y sirven como espacio de nombres para los archivos que contienen. Un ejemplo concreto es que el archivo foo.txt puede existir en ambos directorios /home/greg y /home/other, pero que las dos copias de foo.txt no pueden coexistir en el mismo directorio. Además, para acceder al archivo foo.txt desde fuera del directorio /home/greg, es necesario especificar el nombre del directorio utilizando un separador de directorios, como /home/greg/foo.txt. El mismo principio se aplica a los espacios de nombres en el mundo de la programación. En el mundo de PHP, los espacios de nombres están diseñados para resolver dos problemas que enfrentan los autores de bibliotecas y aplicaciones al reutilizar elementos como clases o bibliotecas de funciones: Colisiones de nombres entre el código que se crea, las clases, funciones o constantes internas de PHP, o las de bibliotecas de terceros. La capacidad de crear alias o acortar nombres como Nombres_Extremadamente_Largos para ayudar a resolver el primer problema y mejorar la legibilidad del código. Los espacios de nombres de PHP proporcionan un medio para agrupar clases, interfaces, funciones o constantes. Aquí hay un ejemplo de sintaxis de los espacios de nombres de PHP: Ejemplo de sintaxis de espacios de nombres ]]> Los nombres de espacios de nombres no son sensibles a mayúsculas/minúsculas. Los espacios de nombres PHP, así como los nombres compuestos que comienzan con estos nombres (como PHP\Classes) están reservados para el uso interno del lenguaje y no deben usarse en el código del espacio de usuario. Definición de espacios de nombres Espacios de nombres Aunque el código PHP válido puede contenerse en un espacio de nombres, solo los siguientes tipos de código pueden verse afectados por los espacios de nombres: las clases (incluyendo las abstractas, los traits y los enums), las interfaces, las funciones y las constantes. Los espacios de nombres se declaran con la palabra clave namespace. Un archivo que contiene un espacio de nombres debe declarar el espacio al principio del archivo, antes de cualquier otro código, con una sola excepción: la palabra clave . Declaración de un espacio de nombres ]]> Los nombres completamente calificados (es decir, los nombres que comienzan con un backslash) no están autorizados en las declaraciones de espacios de nombres, ya que tales construcciones se interpretan como expresiones de espacio de nombres relativo. El único elemento autorizado antes de la declaración de espacio de nombres es la instrucción declare, para definir la codificación del archivo fuente. Además, ningún código no-PHP puede preceder a la declaración de espacio de nombres, incluyendo espacios: Error de declaración de un espacio de nombres ]]> Además, a diferencia de otras estructuras de PHP, el mismo espacio de nombres puede definirse en varios archivos, lo que permite dividir el contenido de un espacio de nombres en varios archivos. Declaración de un subespacio de nombres Subespacio de nombres Al igual que con los archivos y los directorios, los espacios de nombres también son capaces de especificar una jerarquía de espacios de nombres. Por lo tanto, un nombre de espacio de nombres puede definirse con sus subniveles: Declaración de un espacio de nombres con jerarquía ]]> En el ejemplo anterior, se crean la constante MonProjet\Sous\Niveau\CONNEXION_OK, la clase MonProjet\Sous\Niveau\Connexion y la función MonProjet\Sous\Niveau\connecte. Definición de varios espacios de nombres en el mismo archivo Definición de varios espacios de nombres en el mismo archivo También pueden declararse varios espacios de nombres en el mismo archivo. Hay dos sintaxis autorizadas. Declaración de varios espacios de nombres, sintaxis de combinación simple ]]> Esta sintaxis no se recomienda para combinar espacios de nombres en un solo archivo. En su lugar, se recomienda utilizar la sintaxis de llaves. Declaración de varios espacios de nombres, sintaxis de llaves ]]> Se recomienda encarecidamente, como práctica de codificación, no mezclar varios espacios de nombres en el mismo archivo. El uso recomendado es combinar varios scripts PHP en el mismo archivo. Para combinar varios códigos sin espacios de nombres en código con espacio de nombres, solo se admite la sintaxis de llaves. El código global debe estar encerrado por un espacio de nombres sin nombre, como este: Declaración de varios espacios de nombres con un espacio sin nombre ]]> No puede existir ningún código PHP fuera de las llaves del espacio de nombres, excepto para abrir una nueva instrucción declare. Declaración de varios espacios de nombres con un espacio sin nombre (2) ]]> Uso de espacios de nombres: introducción Introducción Antes de discutir el uso de espacios de nombres, es importante comprender cómo PHP deduce qué espacio de nombres está utilizando su código. Puede hacerse una analogía simple entre los espacios de nombres de PHP y un sistema de archivos. Hay tres formas de acceder a un archivo en un sistema de archivos: Un nombre de archivo relativo, como foo.txt. Esto se resuelve en dossiercourant/foo.txt donde dossiercourant es el directorio de trabajo. Si el directorio actual es /home/foo, este nombre se resuelve en /home/foo/foo.txt. Una ruta relativa, como sub-dossier/foo.txt. Esto se resuelve en dossiercourant/sub-dossier/foo.txt. Una ruta absoluta, como /main/foo.txt. Esto se resuelve en /main/foo.txt. El mismo principio puede aplicarse a los espacios de nombres de PHP. Por ejemplo, puede hacer referencia a una clase de tres maneras: Un nombre sin calificador, o una clase sin prefijo, como $a = new foo(); o foo::methodestatique();. Si el espacio de nombres actual es espacedenomscourant, esto se resuelve en espacedenomscourant\foo. Si el espacio de nombres es global, es decir, el espacio de nombres sin nombre, esto se convierte en foo. Una advertencia: los nombres sin calificador para funciones y constantes se tomarán del espacio de nombres global, si la función no está definida en el espacio de nombres actual. Ver Uso de espacios de nombres: retorno al espacio de nombres global para funciones y constantes para más detalles. Un nombre calificado, o una clase con prefijo como $a = new sousespacedenoms\foo(); o sousespacedenoms\foo::methodestatique();. Si el espacio de nombres actual es espacedenomscourant, esto se convierte en espacedenomscourant\sousespacedenoms\foo. Si el código es global, es decir, el espacio de nombres sin nombre, esto se convierte en sousespacedenoms\foo. Un nombre absoluto, o un nombre con prefijo con un operador global como $a = new \espacedenomscourant\foo(); o \espacedenomscourant\foo::methodestatique();. Esto siempre hace referencia al nombre literal especificado en el código: espacedenomscourant\foo. Aquí hay un ejemplo de las tres sintaxis, en código real: file1.php ]]> file2.php ]]> Tenga en cuenta que para acceder a cualquier clase, función o constante global, puede utilizarse un nombre absoluto, como \strlen o \Exception o \INI_ALL. Acceso a clases, funciones y constantes globales desde un espacio de nombres ]]> Espacios de nombres y lenguaje dinámico Espacios de nombres y lenguaje dinámico La implementación de espacios de nombres de PHP está influenciada por su naturaleza dinámica como lenguaje de programación. Por lo tanto, para convertir código como el del siguiente ejemplo en un espacio de nombres: Acceso dinámico a elementos example1.php: ]]> Es necesario utilizar un nombre absoluto (el nombre de la clase, con su prefijo de espacio de nombres). Tenga en cuenta que no hay diferencia entre un nombre absoluto y un nombre calificado en un nombre de clase, función o constante dinámica, lo que hace que el backslash inicial no sea necesario. Acceso dinámico a espacios de nombres ]]> Se recomienda leer la nota sobre la protección de espacios de nombres en cadenas. El comando namespace y la constante __NAMESPACE__ Comando namespace y __NAMESPACE__ PHP admite dos medios para acceder de manera abstracta a los elementos en el espacio de nombres actual, a saber, la constante mágica __NAMESPACE__ y el comando namespace. El valor de __NAMESPACE__ es una cadena que contiene el nombre del espacio de nombres actual. En el espacio global, sin nombre, contiene una cadena vacía. Ejemplo con __NAMESPACE__, en un código con espacio de nombres ]]> Ejemplo con __NAMESPACE__, en un código con espacio de nombres global ]]> La constante __NAMESPACE__ es útil para construir dinámicamente nombres, como: Uso de __NAMESPACE__ para una construcción dinámica de nombres ]]> El comando namespace también puede usarse para solicitar explícitamente un elemento del espacio de nombres actual, o de un subespacio. Es el equivalente para los espacios de nombres del operador self de las clases. El operador namespace, en un espacio de nombres ]]> El operador namespace, en el espacio de nombres global ]]> Uso de espacios de nombres: importación y alias Importación y alias La capacidad de hacer referencia a un nombre absoluto con un alias o importando un espacio de nombres es estratégica. Es un beneficio similar a los enlaces simbólicos en un sistema de archivos. PHP puede crear alias(/importar) constantes, funciones, clases, interfaces, traits, enumeraciones y espacios de nombres. Un alias se crea con el operador use. Aquí hay un ejemplo que presenta los cinco tipos de importación: Importación y alias con el operador use ]]> Tenga en cuenta que para los nombres con ruta (los nombres absolutos que contienen separadores de espacios, como Foo\Bar, en comparación con los nombres globales, como FooBar, que no los contienen), el backslash inicial no es necesario y no se recomienda, ya que los nombres importados deben ser absolutos y no se resuelven relativamente al espacio de nombres actual. Además, PHP admite atajos prácticos, como las instrucciones use múltiples. Importación y alias múltiples con el operador use ]]> La importación se realiza durante la compilación, por lo que no afecta a las clases, funciones y constantes dinámicas. Importación y nombres de espacios dinámicos ]]> Además, la importación solo afecta a los nombres sin calificación. Los nombres absolutos siguen siendo absolutos y no se modifican por una importación. Importación y nombres de espacios absolutos ]]> Reglas de contexto para la importación La palabra clave use debe declararse en el contexto más externo de un archivo (el contexto global) o en las declaraciones de espacio de nombres. Esto se debe a que la importación se realiza durante la compilación y no durante la ejecución, por lo que no se pueden apilar los contextos. El ejemplo siguiente muestra usos incorrectos de la palabra clave use: Reglas de importación incorrectas ]]> Las reglas de importación se basan en archivos, lo que significa que los archivos incluidos no heredarán PAS las reglas de importación del archivo padre. Declaración del grupo <literal>use</literal> Las clases, funciones y constantes importadas desde el mismo &namespace; pueden agruparse en una sola instrucción &use.namespace;. Espacio de nombres global Global Sin ninguna definición de espacio de nombres, todas las clases y las funciones se colocan en el espacio de nombres global: como en PHP antes de que los espacios de nombres fueran introducidos. Al prefijar un nombre con un backslash \, se puede solicitar el uso del espacio de nombres global, incluso en un contexto de espacio de nombres específico. Especificación de espacio de nombres global ]]> Uso de espacios de nombres: retorno al espacio global para funciones y constantes Retorno al espacio global En un espacio de nombres, cuando PHP encuentra un nombre sin calificación, ya sea una clase, una función o una constante, lo resuelve con diferentes prioridades. Los nombres de clases siempre se resuelven con el espacio de nombres actual. Para acceder a clases internas o a clases que no están en un espacio de nombres, es necesario representarlas con su nombre absoluto, como: Acceso a clases globales desde un espacio de nombres ]]> Para las funciones y constantes, PHP las buscará en el espacio global si no puede encontrarlas en el espacio de nombres actual. Acceso a funciones y constantes globales en un espacio de nombres ]]> Reglas de resolución de nombres Reglas de resolución de nombres En el contexto de las reglas de resolución, hay varias definiciones importantes: Definiciones para 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 Es un identificador que comienza con namespace, como namespace\Foo\Bar. Los nombres se resuelven siguiendo las siguientes reglas: Los nombres absolutos siempre se traducen a nombres sin el separador de namespace. Por ejemplo, \A\B se traduce a A\B. Todos los nombres que no son absolutos se traducen con 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 a X\Y\A. El mismo nombre en el namespace global se traduce a A. Para los nombres absolutos, el primer segmento se traduce de acuerdo con la clase/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 a A\B\C\D\E. 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 a A\B\C\D\E. Para los nombres absolutos, el nombre se traduce en relación con la tabla actual de importación 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 manera similar, después de use function A\B\foo; un uso como foo() corresponde al nombre A\B\foo. Para los nombres relativos, si ninguna regla se aplica, y el nombre hace referencia a una clase, el namespace actual sirve como prefijo. Por ejemplo new C() en el namespace A\B corresponde al nombre A\B\C. Para los nombres relativos, si ninguna regla se aplica, y el nombre hace referencia a una función o constante, y el código está fuera del namespace global, el nombre se resuelve durante 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(): Busca una función en el espacio de nombres actual: A\B\foo(). Intenta encontrar y llamar a la función global foo(). Ejemplos de resolución de espacios de nombres ]]> Preguntas frecuentes: lo que debe saber sobre espacios de nombres Preguntas frecuentes 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. Si no utilizo espacios de nombres, ¿debo preocuparme por ellos? ¿Cómo utilizar una clase global o interna desde un espacio de nombres? ¿Cómo utilizar las clases de espacios de nombres, las funciones o las constantes en su propio espacio? ¿Cómo se resuelve un nombre como \mon\nom o \nom? ¿Cómo se resuelve un nombre como mon\nom? ¿Cómo se resuelve un nombre de clase sin calificación, como nom? ¿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. Los nombres importados no deben entrar en conflicto con las clases definidas en el mismo archivo Los espacios de nombres anidados están prohibidos Los nombres de espacios de nombres dinámicos deben proteger el backslash Las constantes no definidas referenciadas con un backslash producen un error fatal 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: Acceso a una clase global desde fuera de un espacio de nombres ]]> Es una funcionalidad equivalente a: Acceder a clases globales fuera de un espacio de nombres ]]> ¿Cómo utilizar una clase global o interna desde un espacio de nombres? Acceso a clases internas desde un espacio de nombres ]]> ¿Cómo utilizar las clases de espacios de nombres, las funciones o las constantes en su propio espacio? Acceso a clases, funciones y constantes internas en un espacio de nombres ]]> ¿Cómo se resuelve un nombre como <literal>\mon\nom</literal> o <literal>\nom</literal>? Los nombres que comienzan con \ siempre se resuelven como son, por lo que \mon\nom es en realidad mon\nom, y \Exception es Exception. Nombres de espacios absolutos ]]> ¿Cómo se resuelve un nombre como <literal>mon\nom</literal>? 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. Nombres calificados ]]> ¿Cómo se resuelve un nombre de clase sin calificación, como <literal>nom</literal>? 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. Clases sin calificación ]]> ¿Cómo se resuelve una función sin calificación o una constante de nombre <literal>nom</literal>? 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. Funciones y constantes sin espacio de nombres ]]> 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 ]]> another.php ]]> file2.php ]]> 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. ]]> Los espacios de nombres anidados están prohibidos PHP no permite anidar espacios de nombres. ]]> Sin embargo, es fácil simular espacios de nombres anidados, como esto: ]]> 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: Peligros de usar espacios de nombres en una cadena ]]> 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. Constantes no definidas ]]> 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. Constantes que no pueden ser redefinidas ]]>