El espacio de nombres PHP (espacio de nombres) se agregó en PHP 5.3. Si ha estudiado C# y Java, el espacio de nombres no es nada nuevo. Sin embargo, todavía tiene un significado muy importante en PHP.
Los espacios de nombres PHP pueden resolver los siguientes dos tipos de problemas:
Conflictos de nombres entre el código escrito por el usuario y las clases/funciones/constantes internas de PHP o clases/funciones/constantes de terceros.
Cree un alias (o nombre corto) para un nombre de identificador muy largo (generalmente definido para aliviar el primer tipo de problema) para mejorar la legibilidad del código fuente.
De forma predeterminada, todos los nombres de constantes, clases y funciones se colocan en el espacio global, al igual que antes de los espacios de nombres admitidos por PHP.
Los espacios de nombres se declaran utilizando la palabra clave namespace. Si un archivo contiene un espacio de nombres, debe declarar el espacio de nombres antes que cualquier otro código. El formato de sintaxis es el siguiente;
<?php // Definir el código en el espacio de nombres 'MiProyecto' namespace MyProject; // ... código...
También puede definir diferentes códigos de espacio de nombres en el mismo archivo, como por ejemplo:
<?php espacio de nombres MiProyecto;const CONNECT_OK = 1;conexión de clase { /* ... */ }función conectar() { /* ... */ }espacio de nombres OtroProyecto;const CONNECT_OK = 1;conexión de clase { /* .. . */ }función conectar() { /* ... */ }?>
No se recomienda utilizar esta sintaxis para definir varios espacios de nombres en un solo archivo. Se recomienda utilizar la siguiente forma de sintaxis entre llaves.
<?phpnamespace MiProyecto { const CONNECT_OK = 1; clase Conexión { /* ... */ } función conectar() { /* ... */ }}espacio de nombres OtroProyecto { const CONNECT_OK = 1; . */ } función conectar() { /* ... */ }}?>
Para combinar código global que no es de espacio de nombres con código de espacio de nombres, solo se puede usar la sintaxis de llaves. El código global debe estar encerrado en una declaración de espacio de nombres sin nombre seguida de llaves, por ejemplo:
<?phpnamespace MiProyecto {const CONNECT_OK = 1;clase Conexión { /* ... */ }función conectar() { /* ... */ }}espacio de nombres { // Código global session_start();$a = MiProyecto connect();echo MiProyectoConexión::start();}?>
El único código legal antes de declarar un espacio de nombres es la declaración de declaración que define la codificación del archivo fuente. Todo el código que no sea PHP, incluidos los espacios en blanco, no puede aparecer antes de una declaración de espacio de nombres.
<?phpdeclare(encoding='UTF-8'); //Definir múltiples espacios de nombres y espacios de nombres de código no incluidos en el espacio de nombres MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect () { / * ... */ }}namespace { // Código global session_start();$a = MiProyectoconnect();echo MiProyectoConexión::start();}?>
El siguiente código provocará un error de sintaxis:
<html><?phpnamespace MyProject; // "<html>" que aparece antes del espacio de nombres causará un error fatal: ¿el espacio de nombres debe ser la primera declaración del script del programa?>
Al igual que la relación entre directorios y archivos, los espacios de nombres PHP también le permiten especificar nombres de espacios de nombres jerárquicos. Por lo tanto, los nombres de los espacios de nombres se pueden definir de forma jerárquica:
<?phpnamespace MyProjectSubLevel; //Declarar un espacio de nombres único jerárquico const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
El ejemplo anterior crea la constante MyProjectSubLevelCONNECT_OK, la clase MyProjectSubLevelConnection y la función MyProjectSubLevelConnect.
Se puede hacer referencia a los nombres de clase en el espacio de nombres PHP de tres maneras:
Un nombre no calificado o un nombre de clase sin prefijo, como $a=new foo() o foo::staticmethod();. Si el espacio de nombres actual es currentnamespace, foo se resolverá en currentnamespacefoo. Si el código que usa foo es global y no contiene código en ningún espacio de nombres, entonces foo se resolverá como foo. Advertencia: si una función o constante en un espacio de nombres no está definida, la función o el nombre constante no calificado se resuelve en una función global o un nombre constante.
Un nombre calificado o un nombre que incluya un prefijo, como $a = new subnamespacefoo() o subnamespacefoo::staticmethod();. Si el espacio de nombres actual es currentnamespace, foo se resolverá en currentnamespacesubnamespacefoo. Si el código que usa foo es global, el código que no está contenido en ningún espacio de nombres, foo se resolverá en subnamespacefoo.
Un nombre completo o un nombre que incluya un operador de prefijo global, por ejemplo, $a = new currentnamespacefoo() o currentnamespacefoo::staticmethod();. En este caso, foo siempre se resuelve con el nombre literal currentnamespacefoo en el código.
A continuación se muestra un ejemplo del uso de estos tres métodos:
código de archivo file1.php
<?phpnamespace FooBarsubnamespace; const FOO = 1;función foo() {}clase foo{ función estática método estático() {}}?>
código de archivo file2.php
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* Nombre no calificado*/foo() // Analizándolo; es la función FooBarfoofoo::staticmethod(); // Se analiza en la clase FooBarfoo y el método es staticmethodecho FOO; Se resuelve en la constante FooBarFOO/* nombre calificado*/subnamespacefoo(); // Se resuelve en la función FooBarsubnamespacefoosubnamespacefoo::staticmethod() // Se resuelve en la clase FooBarsubnamespace; foo, // y métodos de clase staticmethodecho subnamespaceFOO; // analizados a constante FooBarsubnamespaceFOO /* Nombre completo */FooBarfoo(); // Se resuelve en la función FooBarfooFooBarfoo::staticmethod() // Se resuelve en la clase FooBarfoo y la clase Método staticmethodecho FooBarFOO; //Resuelto como constante FooBarFOO?>
Tenga en cuenta que para acceder a cualquier clase, función o constante global, puede utilizar un nombre completo, como strlen() o Exception o INI_ALL.
Acceda a clases, funciones y constantes globales dentro de un espacio de nombres:
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // Llamar a la función global strlen$b = INI_ALL // Acceder a la constante global INI_ALL$; c = new Exception('error'); // ¿Crear una instancia de la clase global Exception?>
La implementación de los espacios de nombres PHP se ve afectada por la naturaleza dinámica del propio lenguaje. Entonces, si desea convertir el código siguiente en un espacio de nombres, acceda a los elementos dinámicamente.
código de archivo ejemplo1.php:
<?phpclass nombre de clase{ función __construct() { echo __METHOD__,"n" }}función nombre de función(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'nombre de clase';$obj = new $a; // imprime nombre de clase::__construct$b = 'nombrefunc';$b() // imprime nombrefuncecho constante('nombreconst'), "n"; // imprime global?>
Debe utilizar un nombre completo (el nombre de la clase, incluido el prefijo del espacio de nombres). Tenga en cuenta que la barra invertida inicial es innecesaria porque no hay diferencia entre nombres calificados y completamente calificados en nombres de clases dinámicas, nombres de funciones o nombres de constantes.
Acceder dinámicamente a elementos de un espacio de nombres
<?phpnamespace namespacename;class classname{ function __construct() { echo __METHOD__,"n"; function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";incluye 'ejemplo1.php' ;$a = 'nombre de clase';$obj = new $a // Nombre de clase de salida::__construct$b = 'funcname';$b(); // Nombre de la función de salida echo constante('constname'), "n" // Salida global/* Si se utilizan comillas dobles, el método de uso es "\namespacename\classname "* /$a = 'namespacenameclassname';$obj = new $a; // Salida namespacenameclassname::__construct$a = 'namespacenameclassname';$obj = new $a; // Salida namespacenameclassname::__construct$b = 'namespacenamefuncname';$b() // Salida namespacenamefuncname$b = 'namespacenamefuncname';$b() // Salida namespacenamefuncnameecho constante( 'namespacenameconstname'), "n" // Salida namespacedecho constante('namespacenameconstname'), "n"; ¿Espacio de nombres de salida?>
PHP admite dos métodos abstractos para acceder a elementos dentro del espacio de nombres actual, la constante mágica __NAMESPACE__ y la palabra clave del espacio de nombres.
El valor de la constante __NAMESPACE__ es una cadena que contiene el nombre del espacio de nombres actual. En el código global, no incluido en ningún espacio de nombres, contiene una cadena vacía.
Ejemplo de __NAMESPACE__, código en un espacio de nombres
<?phpnamespace MiProyecto;echo '"', __NAMESPACE__, '"' // Salida "MiProyecto"?>
Ejemplo de __NAMESPACE__, código global
<?phpecho '"', __NAMESPACE__, '"' // Salida ""?>
La constante __NAMESPACE__ es útil al crear nombres dinámicamente, por ejemplo:
Crea nombres dinámicamente usando __NAMESPACE__
<?phpnamespace MiProyecto;función get($nombredeclase){ $a = __NAMESPACE__ '\' .
El espacio de nombres de palabras clave se puede utilizar para acceder explícitamente a elementos en el espacio de nombres o subespacios de nombres actuales. Es equivalente al operador self en clases.
operador de espacio de nombres, código en el espacio de nombres
<?phpnamespace MyProject;use blahblah como mío; // consulte "Uso de espacios de nombres: importación/alias"blahmine(); // llama a la función blahblahmine()namespaceblahmine(); llama a la función MyProjectblahmine()namespacefunc() // llama a la función MyProjectfunc()namespacesubfunc(); MyProjectsubfunc()namespacecname::method(); // llama al método estático "método" de la clase MyProjectcname$a = new namespacesubcname() // instancia el objeto de la clase MyProjectsub; cname$b = espacio de nombresCONSTANT; // asigna el valor de la constante MiProyectoCONSTANT a $b?>
operador de espacio de nombres, código global
<?phpnamespacefunc(); // llama a la función func()namespacesubfunc(); // llama a la función subfunc()namespacecname::method() // llama al método estático "método" de class cname$a = new namespacesubcname(); // instancia el objeto de la clase subcname$b = namespaceCONSTANT // asigna el valor de la constante CONSTANT a $b?>
El soporte de espacios de nombres PHP tiene dos formas de usar alias o importaciones: usar alias para nombres de clases o usar alias para nombres de espacios de nombres.
En PHP, el alias se implementa mediante el operador use. Aquí hay un ejemplo que utiliza los tres métodos de importación posibles:
1. Utilice el operador use para importar/usar alias
<?phpnamespace foo;use MyFullClassname as Another;// El siguiente ejemplo es el mismo que usar MyFullNSname como NSname use MyFullNSname;// Importar una clase global use ArrayObject;$obj = nuevo espacio de nombresOtro; // Crear una instancia de fooOtro objeto $obj = nuevo Otro // Crear una instancia de micompletonombre de clase NSnamesubnsfunc(); Llame a la función MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // Crear una instancia del objeto ArrayObject // Si no se usa "use ArrayObject", ¿crear una instancia de un objeto fooArrayObject?>
2. Una línea contiene múltiples declaraciones de uso.
<?phpuse MyFullClassname como Otro, MyFullNSname;$obj = new Otro // Crear una instancia de MyFullClassname objeto NSnamesubnsfunc() // Llamar a la función MyFullNSname ; subnsfunc?>
Las operaciones de importación se realizan durante la compilación, pero los nombres de clases dinámicas, nombres de funciones o nombres de constantes no.
3. Importación y nombres dinámicos
<?phpuse MyFullClassname como Otro, MyFullNSname;$obj = new Otro // Crear una instancia de un objeto MyFullClassname $a = 'Otro';$obj = new $a; ¿Otro objeto?>
Además, la operación de importación afecta sólo a nombres calificados y no calificados. Los nombres completos no se ven afectados por las importaciones porque son deterministas.
4. Importación y nombres completos
<?phpuse MyFullClassname como Otro, MyFullNSname;$obj = new Otro; // Crear una instancia de MyFullClassname class $obj = new Another // Crear una instancia de otra clase $obj = new Otro; cosa; // Instanciar minombre de clasecompletoclase de cosa $obj = new Otracosa // ¿Crear una instancia de otraclase de cosa?>
Dentro de un espacio de nombres, cuando PHP encuentra una clase, función o nombre constante no calificado, utiliza una estrategia de precedencia diferente para resolver el nombre. Los nombres de las clases siempre se resuelven en nombres en el espacio de nombres actual. Por lo tanto, al acceder a nombres de clases internos del sistema o no contenidos en el espacio de nombres, debe utilizar el nombre completo, por ejemplo:
1. Acceda a clases globales en el espacio de nombres.
<?phpnamespace ABC;class Exception extends Exception {}$a = new Exception('hi'); // $a es un objeto de clase ABCException $b = new Exception( 'hi'); // $b es un objeto de clase Exception $c = new ArrayObject; // Error fatal, ¿clase ABCArrayObject no encontrada?>
Para funciones y constantes, si la función o constante no existe en el espacio de nombres actual, PHP volverá a utilizar la función o constante en el espacio global.
2. Copia de seguridad de funciones/constantes globales en el espacio de nombres
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n" // Salida "45"echo INI_ALL, " n"; // Salida "7" - use la constante global INI_ALLecho strlen('hi'), "n"; // Salida "2"if (is_array('hi')) { // Salida "no es una matriz" echo "es una matrizn";} else { echo "no es una matrizn";}?>
Si no se define ningún espacio de nombres, todas las clases y funciones se definen en el espacio global, tal como antes de que PHP introdujera el concepto de espacio de nombres. Anteponer un nombre con indica que el nombre está en el espacio global, incluso si el nombre está en otro espacio de nombres.
Utilice instrucciones de espacio global
<?phpnamespace ABC;/* Esta función es ABCfopen */function fopen() { /* ... */ $f = fopen(...); La función fopen devuelve $f;} ?>
Desde la aparición de los espacios de nombres, lo más propenso a errores es, cuando se utiliza una clase, cuál es la ruta de búsqueda para esta clase.
<?phpnamespace A;use BD, CE as F;// Llamada a función foo() // Primero intenta llamar a la función foo() definida en el espacio de nombres "A" // Luego intenta llamar al global function" foo"foo(); // Llama a la función de espacio global "foo" myfoo(); // Llama a la función "foo" definida en el espacio de nombres "Amy" F(); Primero intente llamar a la función "F" definida en el espacio de nombres "A" // Luego intente llamar a la función global "F" // Referencia de clase new B() // Cree la clase "B" definida en el espacio de nombres "A" Un objeto de class "AB" new D(); // Si no se encuentra, intente cargar automáticamente la clase "AB" new D() // Usando reglas de importación, cree un objeto de clase "D" definido en el espacio de nombres "B". " // Si no se encuentra Si se encuentra, intente cargar automáticamente la clase "BD" nueva F(); // Utilizando reglas de importación, crea un objeto de clase "E" definido en el espacio de nombres "C" // Si no lo encuentra, intenta cargar automáticamente la clase "CE" new B(); de la clase "B" definida en el espacio global // Si no se encuentra, intente cargar automáticamente la clase "B" new D() // Cree un objeto de clase "D" definido en el espacio global // Si no se encuentra, intente carga automática clase "D" nueva F(); // Crea un objeto de clase "F" definido en el espacio global // Si no lo encuentra, intenta cargar automáticamente la clase "F" // Llama a un método estático o función de espacio de nombres en otro espacio de nombres Bfoo() ; // Llamar a la función "foo" en el espacio de nombres "AB" B::foo(); // Llamar al método "foo" de la clase "B" definida en el espacio de nombres "A" // Si la clase "AB" es extraviado , luego intente cargar automáticamente la clase "AB" D::foo() // Utilice reglas de importación para llamar al método "foo" de la clase "D" definida en el espacio de nombres "B" // Si la clase "BD" " " Si no se encuentra, intente cargar automáticamente la clase "BD"Bfoo(); // Llama a la función "foo" en el espacio de nombres "B" B::foo(); Función en el espacio global Clase "B". El método "foo" // Si no se encuentra la clase "B", intente cargar automáticamente la clase "B" // Un método o función estático en el espacio de nombres actual AB::foo() // Llamar al espacio de nombres "A"; Método "foo" de la clase "B" definida en A" // Si no se encuentra la clase "AAB", intente cargar automáticamente la clase "AAB"AB::foo() ; // Llame al método "foo" de la clase "B" definida en el espacio de nombres "A" // Si no se encuentra la clase "AB", ¿intenta cargar automáticamente la clase "AB"?>
La resolución de nombres sigue las siguientes reglas:
Las llamadas a nombres completos de funciones, clases y constantes se resuelven en tiempo de compilación. Por ejemplo, el nuevo AB se resuelve en la clase AB .
Todos los nombres no calificados y calificados (no nombres completamente calificados) se convierten en tiempo de compilación de acuerdo con las reglas de importación actuales. Por ejemplo, si el espacio de nombres ABC se importó como C , las llamadas a CDe() se traducirían a ABCDe() .
Dentro de un espacio de nombres, todos los nombres calificados que no se conviertan de acuerdo con las reglas de importación tendrán el nombre del espacio de nombres actual antepuesto. Por ejemplo, si se llama a CDe() dentro del espacio de nombres AB , CDe() se convertirá en ABCDe() .
Los nombres de clase no calificados se convierten en tiempo de compilación de acuerdo con las reglas de importación actuales (se utilizan nombres completos en lugar de nombres cortos de importación). Por ejemplo, si el espacio de nombres ABC se importa como C, new C() se convierte en new ABC() .
Dentro de un espacio de nombres (por ejemplo, AB), las llamadas a funciones a nombres no calificados se resuelven en tiempo de ejecución. Por ejemplo, una llamada a la función foo() se analiza así:
Encuentre una función llamada ABfoo() en el espacio de nombres actual
Intente buscar y llamar a la función foo() en el espacio global .
Las llamadas a nombres no calificados o clases de nombres calificados (nombres no completamente calificados) dentro de un espacio de nombres (por ejemplo, AB ) se resuelven en tiempo de ejecución. El siguiente es el proceso de análisis de llamar a new C() y new DE() : Análisis de new C() :
Busque las clases ABC en el espacio de nombres actual.
Intente cargar automáticamente las clases ABC .
Análisis del nuevo DE() :Anteponga el nombre de la clase al nombre del espacio de nombres actual para que se convierta en: ABDE y luego busque la clase.
Intente cargar automáticamente la clase ABDE .
Para hacer referencia a una clase global en el espacio de nombres global, se debe utilizar el nombre completo new C() .