En general, un proveedor, por sí solo, no es más que el armazón para que un desarrollador empaquete algunas capacidades que desea despachar con la línea de comandos (u otros) clientes. Es un análogo de lo que es un "controlador" dentro de su aplicación MVC.
Por defecto, Zend_Tool usa el IncludePathLoader para encontrar todos
los proveedores que puede ejecutar. Recorre recursivamente todos
los directorios del include path y abre todos los archivos que terminan
en "Manifest.php" o "Provider.php". Todas las clases de estos
archivos se inspeccionan para ver si implementan
Zend_Tool_Framework_Provider_Interface
o Zend_Tool_Framework_Manifest_ProviderManifestable.
Las instancias de la interfaz de proveedor constituyen la funcionalidad
real y todos sus métodos públicos son accesibles como acciones del proveedor.
La interfaz ProviderManifestable, sin embargo, requiere la implementación de un método
getProviders() que devuelve un array de
instancias de la interfaz de proveedor ya instanciadas.
Las siguientes reglas de nomenclatura se aplican en cuanto a cómo puede acceder a los proveedores que fueron encontrados por el IncludePathLoader:
La última parte de su nombre de clase separado por guion bajo se usa como nombre del proveedor, por ejemplo, "My_Provider_Hello" hace que su proveedor sea accesible con el nombre "hello".
Si su proveedor tiene un método
getName(), este se usará en lugar del método anterior para determinar el nombre.Si su proveedor tiene "Provider" como prefijo, por ejemplo se llama
My_HelloProvider, se eliminará del nombre de modo que el proveedor se llamará "hello".
![]() |
Nota |
|---|---|
El IncludePathLoader no sigue los enlaces simbólicos, lo que significa que no puede enlazar la funcionalidad de un proveedor a sus include paths; deben estar físicamente presentes en los include paths. |
Ejemplo 72.1. Exponer sus proveedores con un manifiesto
Puede exponer sus proveedores a Zend_Tool ofreciendo un
manifiesto con un nombre de archivo especial que termine en "Manifest.php".
Un Provider Manifest es una implementación de
Zend_Tool_Framework_Manifest_ProviderManifestable
y requiere que el método getProviders() devuelva
un array de proveedores ya instanciados. Anticipando nuestro primer
proveedor propio My_Component_HelloProvider,
crearemos el siguiente manifiesto:
class My_Component_Manifest
implements Zend_Tool_Framework_Manifest_ProviderManifestable
{
public function getProviders()
{
return array(
new My_Component_HelloProvider()
);
}
}
Como ejemplo, si un desarrollador quiere añadir la capacidad de mostrar
la versión de un archivo de datos con el que trabaja su componente de terceros,
solo hay una clase que el desarrollador necesitaría implementar.
Suponiendo que el componente se llama My_Component, crearía
una clase llamada My_Component_HelloProvider en un
archivo llamado HelloProvider.php en algún lugar del
include_path. Esta clase implementaría
Zend_Tool_Framework_Provider_Interface, y el cuerpo de
este archivo solo tendría que verse como lo siguiente:
class My_Component_HelloProvider
implements Zend_Tool_Framework_Provider_Interface
{
public function say()
{
echo 'Hello from my provider!';
}
}
Dado el código anterior, y suponiendo que el desarrollador desea acceder a esta funcionalidad a través del cliente de consola, la llamada se vería así:
% zf say hello Hello from my provider!
Como se comentó en la sección de arquitectura, Zend_Tool permite
enganchar distintos clientes para usar sus proveedores de Zend_Tool. Para mantener
la compatibilidad con distintos clientes debe usar el objeto de respuesta para devolver mensajes
desde sus proveedores en lugar de usar echo() u otro
mecanismo de salida similar. Reescribiendo nuestro proveedor hello con este conocimiento, quedaría así:
class My_Component_HelloProvider
extends Zend_Tool_Framework_Provider_Abstract
{
public function say()
{
$this->_registry->getResponse
->appendContent("Hello from my provider!");
}
}
Como puede ver, es necesario extender
Zend_Tool_Framework_Provider_Abstract para obtener acceso al
Registry, que contiene la instancia de Zend_Tool_Framework_Client_Response.
El ejemplo "Hello World" anterior es excelente para comandos simples, pero ¿qué pasa con algo más avanzado? A medida que crecen sus necesidades de scripting y de herramientas, puede que necesite la capacidad de aceptar variables. Al igual que las firmas de funciones tienen parámetros, sus solicitudes de herramientas también pueden aceptar parámetros.
Del mismo modo que cada solicitud de herramienta puede aislarse en un método dentro de una clase, los parámetros de una solicitud de herramienta también pueden aislarse en un lugar muy conocido. Los parámetros de los métodos de acción de un proveedor pueden incluir los mismos parámetros que desea que su cliente utilice al llamar a esa combinación de proveedor y acción. Por ejemplo, si quisiera aceptar un nombre en el ejemplo anterior, probablemente haría esto en código OO:
class My_Component_HelloProvider
implements Zend_Tool_Framework_Provider_Interface
{
public function say($name = 'Ralph')
{
echo 'Hello' . $name . ', from my provider!';
}
}
El ejemplo anterior puede entonces llamarse a través de la línea de comandos zf say hello Joe. "Joe" se suministrará al proveedor como un parámetro de la llamada al método. Observe también que, como ve, el parámetro es opcional, lo que significa que también es opcional en la línea de comandos, de modo que zf say hello seguirá funcionando, y usará por defecto el nombre "Ralph".
Hay casos en los que el flujo de trabajo de su proveedor requiere pedir entrada al usuario. Esto puede hacerse solicitando al cliente que pida la entrada adicional requerida llamando a:
class My_Component_HelloProvider
extends Zend_Tool_Framework_Provider_Abstract
{
public function say($name = 'Ralph')
{
$nameResponse = $this->_registry
->getClient()
->promptInteractiveInput("Whats your name?");
$name = $nameResponse->getContent();
echo 'Hello' . $name . ', from my provider!';
}
}
Este comando lanza una excepción si el cliente actual no es capaz de manejar solicitudes interactivas. En el caso del Console Client predeterminado, sin embargo, se le pedirá que introduzca el nombre.
Otra característica interesante que quizá desee implementar es la pretendability (capacidad de simulación). La pretendability es la capacidad de que su proveedor "simule" que está realizando la combinación de acción y proveedor solicitada, y proporcione al usuario toda la información posible sobre lo que haría, sin hacerlo realmente. Esto puede ser una noción importante al realizar modificaciones intensivas de base de datos o del sistema de archivos que el usuario podría no querer hacer en otro caso.
La pretendability es fácil de implementar. Hay dos partes en esta característica: 1) marcar el proveedor como capaz de "simular", y 2) comprobar la solicitud para asegurarse de que a la solicitud actual efectivamente se le pidió que se "simulara". Esta característica se demuestra en el ejemplo de código a continuación.
class My_Component_HelloProvider
extends Zend_Tool_Framework_Provider_Abstract
implements Zend_Tool_Framework_Provider_Pretendable
{
public function say($name = 'Ralph')
{
if ($this->_registry->getRequest()->isPretend()) {
echo 'I would say hello to ' . $name . '.';
} else {
echo 'Hello' . $name . ', from my provider!';
}
}
}
Para ejecutar el proveedor en modo simulado, simplemente llame a:
% zf --pretend say hello Ralph I would say hello Ralph.
También puede ejecutar las acciones de su proveedor en modos "verbose" o "debug". La semántica respecto a estas acciones debe ser implementada por usted en el contexto de su proveedor. Puede acceder a los modos debug o verbose con:
class My_Component_HelloProvider
implements Zend_Tool_Framework_Provider_Interface
{
public function say($name = 'Ralph')
{
if($this->_registry->getRequest()->isVerbose()) {
echo "Hello::say has been called\n";
}
if($this->_registry->getRequest()->isDebug()) {
syslog(LOG_INFO, "Hello::say has been called\n");
}
}
}
Usando la variable de entorno ZF_CONFIG_FILE o el
archivo .zf.ini de su directorio de inicio, puede inyectar parámetros de configuración en
cualquier proveedor de Zend_Tool. El acceso a esta configuración está
disponible a través del registry que se pasa a su proveedor si extiende
Zend_Tool_Framework_Provider_Abstract.
class My_Component_HelloProvider
extends Zend_Tool_Framework_Provider_Abstract
{
public function say()
{
$username = $this->_registry->getConfig()->username;
if(!empty($username)) {
echo "Hello $username!";
} else {
echo "Hello!";
}
}
}
La configuración devuelta es del tipo
Zend_Tool_Framework_Client_Config, pero internamente los
métodos mágicos __get() y __set()
redirigen a un Zend_Config del tipo de configuración dado.
El almacenamiento permite guardar datos arbitrarios para referencia posterior. Esto puede ser útil para tareas de procesamiento por lotes o para reejecuciones de sus tareas. Puede acceder al almacenamiento de forma similar a la configuración:
class My_Component_HelloProvider
extends Zend_Tool_Framework_Provider_Abstract
{
public function say()
{
$aValue = $this->_registry->getStorage()->get("myUsername");
echo "Hello $aValue!";
}
}
La API del almacenamiento es muy simple:
class Zend_Tool_Framework_Client_Storage
{
public function setAdapter($adapter);
public function isEnabled();
public function put($name, $value);
public function get($name, $defaultValue=null);
public function has($name);
public function remove($name);
public function getStreamUri($name);
}
![]() |
Importante |
|---|---|
Al diseñar sus proveedores conscientes de la configuración o el almacenamiento, recuerde comprobar si las claves de configuración de usuario o almacenamiento requeridas realmente existen para un usuario. No obstante, no se encontrará con errores fatales cuando ninguna de ellas se proporcione, ya que se crean vacías bajo demanda. |
![[Note]](images/note.png)
![[Important]](images/important.png)