Varios componentes de Zend Framework son enchufables (pluggable), y permiten la carga
de funcionalidad dinámica especificando un prefijo de clase y una ruta a los archivos de clase
que no necesariamente están en el include_path o no
necesariamente siguen las convenciones de nomenclatura tradicionales.
Zend_Loader_PluginLoader proporciona la funcionalidad común para
este proceso.
El uso básico de PluginLoader sigue las convenciones de nomenclatura
de Zend Framework de una clase por archivo, usando el guion bajo como
separador de directorio al resolver rutas. Permite pasar un prefijo de
clase opcional para anteponer al determinar si una clase de plugin
concreta está cargada. Además, las rutas se buscan en orden LIFO. Debido a la búsqueda
LIFO y a los prefijos de clase, esto le permite definir espacios de nombres para sus
plugins, y así sobrescribir plugins de rutas registradas anteriormente.
Primero, supongamos la siguiente estructura de directorios y archivos de clase, y que el directorio de nivel superior y el directorio de biblioteca están en el include_path:
application/
modules/
foo/
views/
helpers/
FormLabel.php
FormSubmit.php
bar/
views/
helpers/
FormSubmit.php
library/
Zend/
View/
Helper/
FormLabel.php
FormSubmit.php
FormText.php
Ahora, creemos un cargador de plugins para abordar los diversos repositorios de view helper disponibles:
$loader = new Zend_Loader_PluginLoader();
$loader->addPrefixPath('Zend_View_Helper', 'Zend/View/Helper/')
->addPrefixPath('Foo_View_Helper',
'application/modules/foo/views/helpers')
->addPrefixPath('Bar_View_Helper',
'application/modules/bar/views/helpers');
Entonces podemos cargar un view helper dado usando solo la parte del nombre de clase que sigue a los prefijos según se definieron al añadir las rutas:
// load 'FormText' helper:
$formTextClass = $loader->load('FormText'); // 'Zend_View_Helper_FormText';
// load 'FormLabel' helper:
$formLabelClass = $loader->load('FormLabel'); // 'Foo_View_Helper_FormLabel'
// load 'FormSubmit' helper:
$formSubmitClass = $loader->load('FormSubmit'); // 'Bar_View_Helper_FormSubmit'
Una vez cargada la clase, ahora podemos instanciarla.
![]() |
Nota |
|---|---|
En algunos casos, puede usar el mismo prefijo para varias rutas.
|
![]() |
Las rutas se pueden definir en la instanciación |
|---|---|
|
Opcionalmente puede proporcionar un array de pares prefijo / ruta (o prefijo / rutas -- se permiten varias rutas) como parámetro para el constructor:
$loader = new Zend_Loader_PluginLoader(array(
'Zend_View_Helper' => 'Zend/View/Helper/',
'Foo_View_Helper' => 'application/modules/foo/views/helpers',
'Bar_View_Helper' => 'application/modules/bar/views/helpers'
));
|
Zend_Loader_PluginLoader también le permite opcionalmente
compartir plugins entre objetos que admiten plugins, sin necesidad de
utilizar una instancia singleton. Lo hace a través de un registro
estático. Indique el nombre del registro en la instanciación como segundo parámetro
del constructor:
// Store plugins in static registry 'foobar': $loader = new Zend_Loader_PluginLoader(array(), 'foobar');
Otros componentes que instancian el PluginLoader
usando el mismo nombre de registro tendrán entonces acceso a las rutas
y plugins ya cargados.
El ejemplo de la sección anterior muestra cómo añadir rutas a un cargador de plugins. ¿Qué pasa si desea determinar las rutas ya cargadas, o eliminar una o más?
getPaths($prefix = null)devuelve todas las rutas como pares prefijo / ruta si no se proporciona ningún$prefix, o solo las rutas registradas para un prefijo dado si un$prefixestá presente.clearPaths($prefix = null)eliminará todas las rutas registradas por defecto, o solo las asociadas con un prefijo dado, si el$prefixse proporciona y está presente en la pila.removePrefixPath($prefix, $path = null)le permite eliminar selectivamente una ruta específica asociada con un prefijo dado. Si no se proporciona ningún$path, se eliminan todas las rutas para ese prefijo. Si se proporciona un$pathy existe para ese prefijo, solo se eliminará esa ruta.
A veces simplemente desea determinar si una clase de plugin ha sido
cargada antes de realizar una acción. isLoaded() toma un
nombre de plugin, y devuelve el estado.
Otro caso de uso común para PluginLoader es
determinar los nombres de clase de plugin completamente calificados de las clases cargadas;
getClassName() proporciona esta funcionalidad. Normalmente,
esto se usaría junto con isLoaded():
if ($loader->isLoaded('Adapter')) {
$class = $loader->getClassName('Adapter');
$adapter = call_user_func(array($class, 'getInstance'));
}
La carga de plugins puede ser una operación costosa. En esencia, necesita recorrer en bucle cada prefijo, y luego cada ruta del prefijo, hasta que encuentra un archivo que coincide -- y que define la clase esperada. En los casos en que el archivo existe pero no define la clase, se añadirá un error a la pila de errores de PHP, lo cual también es una operación costosa. La pregunta entonces es: ¿cómo puede mantener la flexibilidad de los plugins y también abordar el rendimiento?
Zend_Loader_PluginLoader ofrece una característica opcional para
precisamente esta situación, una caché de inclusión de archivos de clase. Cuando está habilitada,
creará un archivo que contiene todas las inclusiones exitosas, que puede
invocar desde su bootstrap. Usando esta estrategia, puede
mejorar considerablemente el rendimiento de sus servidores de producción.
Ejemplo 42.6. Uso de la caché de inclusión de archivos de clase de PluginLoader
Para usar la caché de inclusión de archivos de clase, simplemente inserte el siguiente código en su bootstrap:
$classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
if (file_exists($classFileIncCache)) {
include_once $classFileIncCache;
}
Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
Obviamente, la ruta y el nombre de archivo variarán según sus necesidades. Este código debe aparecer lo antes posible, para asegurar que los componentes basados en plugins puedan hacer uso de él.
Durante el desarrollo, puede que desee deshabilitar la caché. Un método para hacerlo es usar una clave de configuración para determinar si el cargador de plugins debe cachear o no.
$classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
if (file_exists($classFileIncCache)) {
include_once $classFileIncCache;
}
if ($config->enablePluginLoaderCache) {
Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
}
Esta técnica le permite mantener sus modificaciones en su archivo de configuración en lugar de en el código.
![[Note]](images/note.png)