English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutorial básico de PHP

Tutorial avanzado de PHP

PHP & MySQL

Manual de referencia de PHP

Espacios de nombres de PHP

El espacio de nombres (namespace) de PHP es en PHP 5.3Incluido, si has estudiado C# y Java, los espacios de nombres no son algo nuevo. Sin embargo, en PHP, tienen una importancia bastante significativa.

Los espacios de nombres de PHP pueden resolver dos tipos de problemas:

  • Código escrito por el usuario y las clases internas de PHP/Función/Constantes o clases de terceros/Función/Conflictos de nombres entre constantes.

  • Crear un nombre alternativo (o corto) para un nombre de identificador largo (generalmente para aliviar el primer problema de clase), lo que mejora la legibilidad del código fuente.

Definir espacio de nombres

Por defecto, todos los nombres de constantes, clases y funciones se colocan en el espacio global, al igual que antes de que PHP soportara los espacios de nombres.

El espacio de nombres se declara con la palabra clave namespace. Si un archivo contiene un espacio de nombres, debe declararse antes de cualquier otro código. El formato de sintaxis es el siguiente;

<?php  
// El código se define en el espacio de nombres 'MyProject'.  
namespace MyProject;  
 
// ... código ...

También puede definir código de diferentes espacios de nombres en el mismo archivo, como:

<?php  
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
namespace AnotherProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
?>

No se recomienda usar esta sintaxis para definir múltiples espacios de nombres en un solo archivo. Se recomienda usar la sintaxis de llaves que se muestra a continuación.

<?php
namespace MyProject {
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
}
namespace AnotherProject {
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
}
?>

Para combinar el código global sin espacio de nombres con el código dentro del espacio de nombres, solo se puede usar la sintaxis de forma de llave. El código global debe estar encerrado entre llaves y precedido por una declaración namespace sin nombre, por ejemplo:

<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}
namespace { // Código global
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

Antes de declarar el espacio de nombres, el código legítimo único es la declaración declare para definir el modo de codificación del archivo de origen. Ningún código no PHP, incluidos los símbolos de espacio en blanco, puede aparecer antes de la declaración del espacio de nombres.

<?php
declarar(encoding='UTF-8',-8'); //Definir múltiples espacios de nombres y código no incluido en el espacio de nombres
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}
namespace { // Código global
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

El siguiente código generará un error de sintaxis:

<html>
<?php
namespace MyProject; // El espacio de nombres antes de '<html>' causará un error fatal - El espacio de nombres debe ser la primera declaración de la secuencia de comandos
?>

Subespacio de nombres

Al igual que las relaciones entre directorios y archivos, el espacio de nombres de PHP también permite especificar nombres de espacios de nombres jerárquicos. Por lo tanto, el nombre del espacio de nombres se puede definir de manera jerárquica:

<?php
namespace MyProject\Sub\Level;  //Declarar un espacio de nombres jerárquico
const CONNECT_OK = 1;
class Connection { /* ... */ }
function Connect() { /* ... */  }
?>

El siguiente ejemplo crea la constante MyProject\Sub\Level\CONNECT_OK, la clase MyProject\Sub\Level\Connection y la función MyProject\Sub\Level\Connect.

Uso de espacio de nombres

El nombre de la clase en el espacio de nombres de PHP se puede referir de tres maneras:

  • Nombre no definido o nombre de clase sin prefijoPor ejemplo, $a = new foo(); o foo::staticmethod();. Si el espacio de nombres actual es currentnamespace, foo se interpretará como currentnamespace\foo. Si el código que utiliza foo es global, no incluido en ningún espacio de nombres, foo se interpretará como foo. Advertencia: si no se define la función o la constante en el espacio de nombres, el nombre no definido de la función o la constante se interpretará como el nombre de la función o la constante global.

  • Nombre definido o nombre con prefijoPor ejemplo, $a = new subnamespace\foo(); o subnamespace\foo::staticmethod();. Si el espacio de nombres actual es currentnamespace, foo se interpretará como currentnamespace\subnamespace\foo. Si el código que utiliza foo es global, no incluido en ningún espacio de nombres, foo se interpretará como subnamespace\foo.

  • Nombre completamente cualificado, o nombres que contienen el operador de prefijo global}}Por ejemplo, $a = new \currentnamespace\foo(); o \currentnamespace\foo::staticmethod();. En este caso, foo siempre se analiza como el nombre literal (literal name) currentnamespace\foo del código.

A continuación, se muestra un ejemplo de uso de estos tres métodos:

archivo file1código de archivo .php

<?php
espacio de nombres namespace Foo\Bar\subnamespace; 
constante const FOO = 1;
función function foo() {}
clase class foo
{
    función estática static function staticmethod() {}
}
?>

archivo file2código de archivo .php

<?php
espacio de nombres namespace Foo\Bar;
incluir include 'file1.php';
constante const FOO = 2;
función function foo() {}
clase class foo
{
    función estática static function staticmethod() {}
}
/* Nombre no cualificado */
foo(); // Analizado como la función Foo\Bar\foo
foo::staticmethod(); // Analizado como la clase Foo\Bar\foo , método staticmethod
echo FOO; // Analizado como la constante Foo\Bar\FOO
/* Nombre cualificado */
subnamespace\foo(); // Analizado como la función Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // Analizado como la clase Foo\Bar\subnamespace\foo,
                                  // así como los métodos de la clase staticmethod
echo subnamespace\FOO; // Analizado como la constante Foo\Bar\subnamespace\FOO
                                  
/* Nombre completamente cualificado */
\Foo\Bar\foo(); // Analizado como la función Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // Analizado como la clase Foo\Bar\foo, así como los métodos de la clase staticmethod
echo \Foo\Bar\FOO; // Analizado como la constante Foo\Bar\FOO
?>

Nota: para acceder a cualquier clase global, función o constante, se puede usar el nombre completamente cualificado, por ejemplo \strlen() o \Exception o \INI_ALL.

Acceso a clases globales, funciones y constantes dentro del espacio de nombres:

<?php
espacio de nombres Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // Llamada a la función global strlen
$b = \INI_ALL; // Acceso a la constante global INI_ALL
$c = new \Exception('error'); // Ejemplo de clase global Exception
?>

Espacios de nombres y características dinámicas del lenguaje

La implementación de los espacios de nombres en PHP está influenciada por sus características dinámicas propias. Por lo tanto, si se debe convertir el siguiente código a un espacio de nombres, el acceso a los elementos dinámicos.

example1Código del archivo .php:

<?php
class classname
{
    function __construct()
    {
        echo __METHOD__, '\n';
    }
}
function funcname()
{
    echo __FUNCTION__, '\n';
}
const constname = 'global';
$a = 'classname';
$obj = new $a; // Imprime classname::__construct
$b = 'funcname';
$b(); // Imprime funcname
echo constante('constname'), '\n'; // Imprime global
?>

Es necesario usar el nombre completo (que incluye el nombre de la clase con el prefijo del espacio de nombres). Nota: ya que en los nombres de clase, funciones o constantes dinámicos, el nombre completo y el nombre limitado no tienen diferencia, el guión oblicuo inicial no es necesario.

Acceso dinámico a los elementos del espacio de nombres

<?php
namespace namespacename;
class classname
{
    function __construct()
    {
        echo __METHOD__, '\n';
    }
}
function funcname()
{
    echo __FUNCTION__, '\n';
}
const constname = 'namespaced';
include 'example1.php';
$a = 'classname';
$obj = new $a; // Salida: classname::__construct
$b = 'funcname';
$b(); // Salida: nombre de la función
echo constante('constname'), '\n'; // Salida: global
/* Si se usan comillas dobles, el uso es "\\namespacename\\classname"*/
$a = '\namespacename\classname';
$obj = new $a; // Salida: namespacename\classname::__construct
$a = 'namespacename\classname';
$obj = new $a; // Salida: namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // salida "namespacename\funcname"
$b = 'namespacename\funcname';
$b(); // salida "namespacename\funcname"
echo constante('\namespacename\constname'), "\n"; // salida "namespaced"
echo constante('namespacename\constname'), "\n"; // salida "namespaced"
?>

palabra clave namespace y constante __NAMESPACE__

PHP admite dos métodos abstractos para acceder a los elementos internos del namespace actual, la constante __NAMESPACE__ y la palabra clave namespace.

El valor de la constante __NAMESPACE__ es una cadena que contiene el nombre del namespace actual. En el código global, que no está incluido en ningún namespace, contiene una cadena vacía.

__NAMESPACE__ ejemplo, en el código del namespace

<?php
namespace MyProject;
echo '"', __NAMESPACE__, '"'; // salida "MyProject"
?>

__NAMESPACE__ ejemplo, código global

<?php
echo '"', __NAMESPACE__, '"'; // salida ""
?>

La constante __NAMESPACE__ es muy útil para crear nombres dinámicamente, por ejemplo:

Uso de __NAMESPACE__ para crear nombres dinámicamente

<?php
namespace MyProject;
función get($classname)
{
    $a = __NAMESPACE__ . '\\' . $classname;
    devuelve new $a;
}
?>

La palabra clave namespace se puede usar para acceder explícitamente a los elementos del namespace actual o de los subnamespaces. Es equivalente al operador self en las clases.

operador de namespace, código en el namespace

<?php
namespace MyProject;
usa blah\blah como mine; // ver "Usando namespaces: importando/aliasing"
blah\mine(); // llama a la función blah\blah\mine()
namespace\blah\mine(); // llama a la función MyProject\blah\mine()
namespace\func(); // llama a la función MyProject\func()
namespace\sub\func(); // llama a la función MyProject\sub\func()
namespace\cname::method(); // llama al método estático "method" de la clase MyProject\cname
$a = new namespace\sub\cname(); // instancia el objeto de la clase MyProject\sub\cname
$b = namespace\CONSTANT; // Asigna el valor de la constante MyProject\CONSTANT a $b
?>

Operador namespace, código global

<?php
namespace\func(); // Llama a la función func()
namespace\sub\func(); // Llama a la función sub\func()
namespace\cname::method(); // Llama al método estático "method" de la clase cname
$a = new namespace\sub\cname(); // Instancia un objeto de la clase sub\cname
$b = namespace\CONSTANT; // Asigna el valor de la constante CONSTANT a $b
?>

Uso de namespace: alias/Importación

PHP soporta dos formas de usar alias o importar: usar alias para nombres de clase o usar alias para nombres de espacio.

En PHP, los alias se implementan a través del operador use. A continuación se muestra un ejemplo de uso de todos los tres métodos posibles de importación:

1、 Uso del operador use para importar/Uso de alias

<?php
namespace foo;
use My\Full\Classname as Another;
// El siguiente ejemplo es equivalente a use My\Full\NSname as NSname
use My\Full\NSname;
// Importación de una clase global
use \ArrayObject;
$obj = new namespace\Another; // Ejemplificación de un objeto foo\Another
$obj = new Another; // Ejemplificación de un objeto My\Full\Classname
NSname\subns\func(); // Llamada a la función My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // Ejemplificación de un objeto ArrayObject
// Si no se utiliza "use \ArrayObject" , se ejemplifica un objeto foo\ArrayObject
?>

2、 多个use语句在一行中

<?php
usar My\Full\Classname como Another, My\Full\NSname
$obj = new Another; // Ejemplificación de un objeto My\Full\Classname
NSname\subns\func(); // Llamada a la función My\Full\NSname\subns\func
?>

La importación se realiza en tiempo de compilación, pero los nombres de clases, funciones o constantes dinámicas no lo son.

3、导入和动态名称

<?php
usar My\Full\Classname como Another, My\Full\NSname
$obj = new Another; // Ejemplificación de un objeto My\Full\Classname
$a = 'Another';
$obj = new $a;      // instanciar un objeto Another
?>

Además, la operación de importación solo afecta a nombres no limitados y nombres completamente cualificados. Los nombres completamente cualificados, ya que están determinados, no están influenciados por la importación.

4、importación y nombre completamente cualificado

<?php
usar My\Full\Classname como Another, My\Full\NSname
$obj = new Another; // instanciar la clase My\Full\Classname
$obj = new \Another; // instanciar la clase Another
$obj = new Another\thing; // instanciar la clase My\Full\Classname\thing
$obj = new \Another\thing; // instanciar la clase Another\thing
?>

usar espacio de nombres: función global de respaldo/constante

En un espacio de nombres, cuando PHP encuentra un nombre no limitado de clase, función o constante, utiliza diferentes estrategias de prioridad para resolver ese nombre. Los nombres de clase siempre se resuelven al nombre en el espacio de nombres actual. Por lo tanto, al acceder a clases internas o no incluidas en el espacio de nombres, se debe usar el nombre completamente cualificado, por ejemplo:

1、acceso a clase global en el espacio de nombres

<?php
namespace A\B\C;
class Exception extends \Exception {}
$a = new Exception('hi'); // $a es un objeto de la clase A\B\C\Exception
$b = new \Exception('hi'); // $b es un objeto de la clase Exception
$c = new ArrayObject; // error fatal, no se encuentra la clase A\B\C\ArrayObject
?>

Para las funciones y constantes, si no existe la función o constante en el espacio de nombres actual, PHP recurrirá a la función o constante global.

2、función global de respaldo en el espacio de nombres/constante

<?php
namespace A\B\C;
constante E_ERROR = 45;
función strlen($str)
{
    devolver \strlen($str) - 1;
}
echo E_ERROR, "\n"; // salida ""45"
echo INI_ALL, "\n"; // salida ""7" - usar constante global INI_ALL
echo strlen('hi'), "\n"; // salida ""1"
if (is_array('hi')) { // salida "no es array"
    echo "es array\n";
} else {
    echo "no es array\n";
}
?>

Espacio de nombres global

Si no se define ningún espacio de nombres, todas las definiciones de clases y funciones están en el espacio de nombres global, igual que antes de la introducción del concepto de espacio de nombres en PHP. Se añade el prefijo \ delante del nombre para indicar que ese nombre es un nombre en el espacio de nombres global, incluso si ese nombre se encuentra en otros espacios de nombres.

Uso de la declaración global

<?php
namespace A\B\C;
/* Esta función es A\B\C\fopen */
function fopen() { 
     /* ... */
     $f = \fopen(...); // Llamar a la función global fopen
     return $f;
} 
?>

Orden de los espacios de nombres

Desde que se introdujeron los espacios de nombres, uno de los errores más comunes es cuando se usa una clase, ¿cómo es la ruta de búsqueda de esta clase?

<?php
namespace A;
use B\D, C\E as F;
// Llamada de función
foo();      // Primero se intenta llamar a la función definida en el espacio de nombres "A" "foo()"
            // Se intenta llamar nuevamente a la función global "foo"
\foo();     // Se llama a la función global "foo" 
my\foo();   // Se llama a la función "foo" definida en el espacio de nombres "A\my" 
F();        // Primero se intenta llamar a la función definida en el espacio de nombres "A" "F" 
            // Se intenta llamar nuevamente a la función global "F"
// Referencia de clase
new B();    // Se crea un objeto de la clase "B" definida en el espacio de nombres "A"
            // Si no se encuentra, se intenta cargar automáticamente la clase "A\B"
new D();    // Se crea un objeto de la clase "D" definida en el espacio de nombres "B" usando las reglas de importación
            // Si no se encuentra, se intenta cargar automáticamente la clase "B\D"
new F();    // Se crea un objeto de la clase "E" definida en el espacio de nombres "C" usando las reglas de importación
            // Si no se encuentra, se intenta cargar automáticamente la clase "C\E"
new \B();   // Se crea un objeto de la clase "B" definida en el espacio de nombres global
            // Si no se encuentra, se intenta cargar automáticamente la clase "B"
new \D();   // Se crea un objeto de la clase "D" definida en el espacio de nombres global
            // Si no se encuentra, se intenta cargar automáticamente la clase "D"
new \F();   // Se crea un objeto de la clase "F" definida en el espacio de nombres global
            // Si no se encuentra, se intenta cargar automáticamente la clase "F"
// Se llama a un método estático o función de espacio de nombres en otro espacio de nombres
B\foo();    // Se llama a la función "foo" en el espacio de nombres "A\B"
B::foo();   // Llamar al método "foo" de la clase "B" definida en el espacio de nombres "A"
            // Si no se encuentra la clase "A\B", se intenta cargar automáticamente 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 la clase "B\D" no se encuentra, se intenta cargar automáticamente la clase "B\D"
\B\foo();   // Llamar a la función "foo" en el espacio de nombres "B" 
\B::foo();  // Llamar al método "foo" de la clase "B" en el espacio global
            // Si la clase "B" no se encuentra, se intenta cargar automáticamente la clase "B"
// Métodos estáticos o funciones en el espacio de nombres actual
A\B::foo();   // Llamar al método "foo" de la clase "B" definida en el espacio de nombres "A\A"
              // Si la clase "A\A\B" no se encuentra, se intenta cargar automáticamente la clase "A\A\B"
\A\B::foo();  // Llamar al método "foo" de la clase "B" definida en el espacio de nombres "A"
              // Si la clase "A\B" no se encuentra, se intenta cargar automáticamente la clase "A\B"
?>

El análisis de nombres sigue las siguientes reglas:

  1. Las llamadas a funciones, clases y constantes de nombres completamente limitados se resuelven en tiempo de compilación. Por ejemplo      new \A\B se resuelve como clase A\B.

  2. Todos los nombres no limitados y los nombres limitados (no nombres completamente limitados) se convierten según las reglas de importación en tiempo de compilación. Por ejemplo, si el espacio de nombres     A\B\C se importa como CEntonces, la llamada a C\D\e()     La llamada se convierte en A\B\C\D\e().

  3. Dentro del espacio de nombres, todos los nombres limitados que no se han convertido según las reglas de importación se añaden el nombre del espacio de nombres actual delante. Por ejemplo, en el espacio de nombres     A\B La llamada interna C\D\e(),entonces C\D\e()     se convierte en A\B\C\D\e() .

  4. Los nombres de clase no limitados se convierten según las reglas de importación en tiempo de compilación (usando nombres completos en lugar de nombres cortos de importación). Por ejemplo, si el espacio de nombres     A\B\C Importado como C, entonces new C()     se convierte en new A\B\C() .

  5. Dentro del espacio de nombres (por ejemplo A\B),las llamadas a funciones de nombres no limitados se resuelven en tiempo de ejecución. Por ejemplo, la llamada a la función      foo() La llamada se resuelve de la siguiente manera:

    1. Buscar en el espacio de nombres actual el nombre A\B\foo() la función

    2. Intentar buscar y llamar global(global) la función en el espacio foo().

  6. en el espacio de nombres (por ejemploA\B)Las llamadas a nombres no limitados o nombres limitados de clase (no nombres completamente limitados) se resuelven en tiempo de ejecución. A continuación se muestra la llamada      new C() y new D\E() El proceso de explicación:       new C()La explicación: new D\E()La explicación: para referirse a la clase global del espacio de nombres global, es necesario usar el nombre completo new \C().

    1. Añadir el nombre del espacio de nombres actual delante del nombre de la clase para convertirse en:A\B\D\E,luego buscar la clase.

    2. Intentar cargar automáticamente la clase A\B\D\E.

    3. Buscar en el espacio de nombres actualA\B\Cclase.

    4. Intentar cargar automáticamente la claseA\B\C.