TigerZF
🌐Español

42.2. El Autoloader

Zend_Loader_Autoloader introduce una solución de autocarga completa para Zend Framework. Se ha diseñado teniendo en cuenta varios objetivos:

  • Proporcionar un verdadero autoloader de namespaces. (Las versiones anteriores interceptaban todos los namespaces del usuario.)

  • Permitir registrar callbacks arbitrarios como autoloaders, y gestionarlos como una pila. (En el momento de escribir esto, esto supera algunos problemas con spl_autoload, que no permite volver a registrar un callback que utiliza un método de instancia.)

  • Permitir la coincidencia optimista de namespaces para proporcionar una resolución de clases más rápida.

Zend_Loader_Autoloader implementa un singleton, lo que lo hace accesible universalmente. Esto proporciona la capacidad de registrar autoloaders adicionales desde cualquier parte de su código según sea necesario.

42.2.1. Uso del Autoloader

La primera vez que se recupera una instancia del autoloader, este se registra a sí mismo con spl_autoload. Se recupera una instancia usando el método getInstance():

$autoloader = Zend_Loader_Autoloader::getInstance();

De forma predeterminada, el autoloader está configurado para coincidir con los namespaces "Zend_" y "ZendX_". Si tiene su propio código de librería que utiliza su propio namespace, puede registrarlo con el autoloader usando el método registerNamespace(). Por ejemplo, si el código de su librería tiene el prefijo "My_", podría hacerlo de la siguiente manera:

$autoloader->registerNamespace('My_');
[Note] Prefijos de namespace

Observará que el ejemplo anterior usa "My_" y no "My". Esto se debe a que Zend_Loader_Autoloader está pensado como un autoloader de propósito general, y no asume que un determinado prefijo de namespace de clase incluya un guion bajo. Si el namespace de su clase incluye uno, debe incluirlo al registrar su namespace.

También puede registrar callbacks de autoloader arbitrarios, opcionalmente con un namespace específico (o grupo de namespaces). Zend_Loader_Autoloader intentará hacerlos coincidir primero antes de usar su mecanismo interno de autocarga.

Como ejemplo, puede que desee utilizar uno o más componentes de eZcomponents con su aplicación de Zend Framework. Para usar sus capacidades de autocarga, añádalo a la pila del autoloader usando pushAutoloader():

$autoloader->pushAutoloader(array('ezcBase', 'autoload'), 'ezc');

Esto le indica al autoloader que use el autoloader de eZcomponents para las clases que comienzan con "ezc".

Puede usar el método unshiftAutoloader() para añadir el autoloader al principio de la cadena de autoloaders.

De forma predeterminada, Zend_Loader_Autoloader no realiza supresión de errores cuando utiliza su autoloader interno, el cual utiliza Zend_Loader::loadClass(). La mayoría de las veces, esto es exactamente lo que se desea. Sin embargo, puede haber casos en los que se desee suprimirlos. Puede hacerlo usando suppressNotFoundWarnings():

$autoloader->suppressNotFoundWarnings(true);

Finalmente, puede haber ocasiones en las que quiera que el autoloader cargue cualquier namespace. Por ejemplo, las librerías de PEAR no comparten un namespace común, lo que hace que especificar namespaces individuales sea difícil cuando se usan muchos componentes de PEAR. Puede usar el método setFallbackAutoloader() para que el autoloader actúe como un catch-all:

$autoloader->setFallbackAutoloader(true);
[Note] Carga de clases desde namespaces de PHP

A partir de la versión 1.10.0, Zend Framework ahora permite cargar clases desde namespaces de PHP. Este soporte sigue las mismas directrices e implementación que las que se encuentran en la implementación de referencia PHP Framework Interop Group PSR-0.

Bajo esta directriz, se aplican las siguientes reglas:

  • Cada separador de namespace se convierte en un DIRECTORY_SEPARATOR al cargar desde el sistema de archivos.

  • Cada carácter "_" en el NOMBRE DE CLASE se convierte en un DIRECTORY_SEPARATOR. El carácter "_" no tiene un significado especial en el namespace.

  • El namespace y la clase totalmente calificados se sufijan con ".php" al cargar desde el sistema de archivos.

Como ejemplos:

  • \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php

  • \namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php

  • \namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

42.2.2. Selección de una versión de Zend Framework

Normalmente, usará la versión de Zend Framework con la que vino el autoloader que instancia. Sin embargo, al desarrollar un proyecto, a menudo resulta útil rastrear versiones específicas, ramas mayores o menores, o simplemente la última versión. Zend_Loader_Autoloader, a partir de la versión 1.10, ofrece algunas funciones para ayudar a gestionar esta tarea.

Imagine el siguiente escenario:

  • Durante el desarrollo, quiere rastrear la última versión de Zend Framework que tiene instalada, para poder asegurarse de que la aplicación funciona cuando actualice entre versiones.

    Sin embargo, al pasar a Control de calidad, necesita tener algo más de estabilidad, por lo que quiere usar la última revisión instalada de una versión menor específica.

    Finalmente, al pasar a producción, quiere fijarse a una versión instalada específica, para asegurarse de que no se produzcan fallos si o cuando añada nuevas versiones de Zend Framework a su servidor.

El autoloader le permite hacer esto con el método setZfPath(). Este método toma dos argumentos: una ruta a un conjunto de instalaciones de Zend Framework, y una versión a usar. Una vez invocado, antepone una ruta al include_path que apunta a la librería de instalación de Zend Framework correspondiente.

El directorio que especifique como su ruta debe tener un árbol como el siguiente:

ZendFramework/
|-- 1.9.2/
|   |-- library/
|-- ZendFramework-1.9.1-minimal/
|   |-- library/
|-- 1.8.4PL1/
|   |-- library/
|-- 1.8.4/
|   |-- library/
|-- ZendFramework-1.8.3/
|   |-- library/
|-- 1.7.8/
|   |-- library/
|-- 1.7.7/
|   |-- library/
|-- 1.7.6/
|   |-- library/

(donde ruta apunta al directorio "ZendFramework" en el ejemplo anterior)

Tenga en cuenta que cada subdirectorio debe contener el directorio library, que contiene el código real de la librería de Zend Framework. Los nombres de los subdirectorios individuales pueden ser números de versión, o simplemente el contenido descomprimido de un tarball/zipfile de distribución estándar de Zend Framework.

Ahora, abordemos los casos de uso. En el primer caso de uso, en desarrollo, queremos rastrear la última instalación de código fuente. Podemos hacer eso pasando "latest" como versión:

$autoloader->setZfPath($path, 'latest');

En el ejemplo anterior, esto se asignará al directorio ZendFramework/1.9.2/library/; puede verificar esto comprobando el valor de retorno de getZfPath().

En la segunda situación, para control de calidad, digamos que queremos fijarnos a la versión menor 1.8, usando la última instalación que tengamos para esa versión. Puede hacerlo de la siguiente manera:

$autoloader->setZfPath($path, '1.8');

En este caso, encontrará el directorio ZendFramework/1.8.4PL1/library/.

En el último caso, para producción, nos fijaremos a una versión específica -- 1.7.7, ya que eso era lo disponible cuando Control de Calidad realizó pruebas antes de nuestro lanzamiento.

$autoloader->setZfPath($path, '1.7.7');

Como era de esperar, encuentra el directorio ZendFramework/1.7.7/library/.

También puede especificar estos valores en el archivo de configuración que utiliza con Zend_Application. Para hacerlo, especificaría la siguiente información:

[production]
autoloaderZfPath = "path/to/ZendFramework"
autoloaderZfVersion = "1.7.7"

[qa]
autoloaderZfVersion = "1.8"

[development]
autoloaderZfVersion = "latest"

Observe las diferentes secciones de entorno, y la diferente versión especificada en cada entorno; estos factores permitirán que Zend_Application configure el autoloader apropiadamente.

[Warning] Implicaciones de rendimiento

Para un mejor rendimiento, no use esta función, o especifique una versión específica de Zend Framework (es decir, no "latest", una revisión mayor como "1", o una revisión menor como "1.8"). De lo contrario, el autoloader necesitará escanear la ruta proporcionada en busca de directorios que coincidan con el criterio -- una operación algo costosa de realizar en cada solicitud.

42.2.3. La interfaz Autoloader

Además de poder especificar callbacks arbitrarios como autoloaders, Zend Framework también define una interfaz que las clases de autocarga pueden implementar, Zend_Loader_Autoloader_Interface:

interface Zend_Loader_Autoloader_Interface
{
    public function autoload($class);
}

Cuando use esta interfaz, simplemente puede pasar una instancia de clase a los métodos pushAutoloader() y unshiftAutoloader() de Zend_Loader_Autoloader:

// Assume Foo_Autoloader implements Zend_Loader_Autoloader_Interface:
$foo = new Foo_Autoloader();

$autoloader->pushAutoloader($foo, 'Foo_');

42.2.4. Referencia del Autoloader

A continuación, encontrará una guía de los métodos disponibles en Zend_Loader_Autoloader.

Tabla 42.1. Métodos de Zend_Loader_Autoloader

Método Valor de retorno Parámetros Descripción
getInstance() Zend_Loader_Autoloader N/D

Recupera la instancia singleton de Zend_Loader_Autoloader. En la primera recuperación, se registra a sí misma con spl_autoload. Este método es estático.

resetInstance() void N/D

Restablece el estado de la instancia singleton de Zend_Loader_Autoloader a su estado original, anulando el registro de todos los callbacks de autoloader y todos los namespaces registrados.

autoload($class) string|FALSE
  • $class, obligatorio. Una cadena con el nombre de la clase a cargar.

Intenta resolver un nombre de clase a un archivo y cargarlo.

setDefaultAutoloader($callback) Zend_Loader_Autoloader
  • $callback, obligatorio.

Especifica un callback de PHP alternativo para usar como la implementación de autoloader predeterminada.

getDefaultAutoloader() callback N/D

Recupera la implementación de autoloader predeterminada; de forma predeterminada, esta es Zend_Loader::loadClass().

setAutoloaders(array $autoloaders) Zend_Loader_Autoloader
  • $autoloaders, obligatorio.

Establece una lista de autoloaders concretos para usar en la pila de autoloaders. Cada elemento en el array de autoloaders debe ser un callback de PHP.

getAutoloaders() Array N/D

Recupera la pila interna de autoloaders.

getNamespaceAutoloaders($namespace) Array
  • $namespace, obligatorio

Obtiene todos los autoloaders que se han registrado para cargar un namespace específico.

registerNamespace($namespace) Zend_Loader_Autoloader
  • $namespace, obligatorio.

Registra uno o más namespaces con el autoloader predeterminado. Si $namespace es una cadena, registra ese namespace; si es un array de cadenas, registra cada una como un namespace.

unregisterNamespace($namespace) Zend_Loader_Autoloader
  • $namespace, obligatorio.

Anula el registro de uno o más namespaces del autoloader predeterminado. Si $namespace es una cadena, anula el registro de ese namespace; si es un array de cadenas, anula el registro de cada una como un namespace.

getRegisteredNamespaces() Array N/D

Devuelve un array de todos los namespaces registrados con el autoloader predeterminado.

suppressNotFoundWarnings($flag = null) boolean|Zend_Loader_Autoloader
  • $flag, opcional.

Establece o recupera el valor del flag utilizado para indicar si la implementación de autoloader predeterminada debe suprimir las advertencias de "archivo no encontrado". Si no se pasan argumentos o se pasa un valor NULL, devuelve un booleano indicando el estado del flag; si se pasa un booleano, el flag se establece a ese valor y se devuelve la instancia del autoloader (para permitir el encadenamiento de métodos).

setFallbackAutoloader($flag) Zend_Loader_Autoloader
  • $flag, obligatorio.

Establece el valor del flag utilizado para indicar si el autoloader predeterminado debe usarse como autoloader de reserva o catch-all para todos los namespaces.

isFallbackAutoloader() Boolean N/D

Recupera el valor del flag utilizado para indicar si el autoloader predeterminado debe usarse como autoloader de reserva o catch-all para todos los namespaces. De forma predeterminada, esto es FALSE.

getClassAutoloaders($class) Array
  • $class, obligatorio.

Obtiene la lista de autoloaders namespaced que podrían potencialmente coincidir con la clase proporcionada. Si ninguno coincide, se devuelven todos los autoloaders globales (sin namespace).

unshiftAutoloader($callback, $namespace = '') Zend_Loader_Autoloader
  • $callback, obligatorio. Un callback de PHP válido

  • $namespace, opcional. Una cadena que representa un prefijo de namespace de clase.

Añade una implementación de autoloader concreta al principio de la pila interna de autoloaders. Si se proporciona un namespace, ese namespace se usará para coincidir de forma optimista; de lo contrario, el autoloader se considerará un autoloader global.

pushAutoloader($callback, $namespace = '') Zend_Loader_Autoloader
  • $callback, obligatorio. Un callback de PHP válido

  • $namespace, opcional. Una cadena que representa un prefijo de namespace de clase.

Añade una implementación de autoloader concreta al final de la pila interna de autoloaders. Si se proporciona un namespace, ese namespace se usará para coincidir de forma optimista; de lo contrario, el autoloader se considerará un autoloader global.

removeAutoloader($callback, $namespace = '') Zend_Loader_Autoloader
  • $callback, obligatorio. Un callback de PHP válido

  • $namespace, opcional. Una cadena que representa un prefijo de namespace de clase, o un array de cadenas de namespace.

Elimina una implementación de autoloader concreta de la pila interna de autoloaders. Si se proporcionan un namespace o namespaces, el callback se eliminará solo de ese namespace o namespaces.