TigerZF
🌐Español

72.3. Arquitectura

72.3.1. Registro

Debido a que los proveedores y manifiestos pueden provenir de cualquier lugar del include_path, se proporciona un registro para simplificar el acceso a las diversas piezas de la cadena de herramientas. Este registro se inyecta en los componentes que tienen conocimiento del registro, los cuales pueden luego extraer dependencias de ellos según sea necesario. La mayoría de las dependencias registradas con el registro serán repositorios específicos de subcomponentes.

La interfaz del registro consiste en la siguiente definición:

interface Zend_Tool_Framework_Registry_Interface
{
    public function setClient(Zend_Tool_Framework_Client_Abstract $client);
    public function getClient();
    public function setLoader(Zend_Tool_Framework_Loader_Abstract $loader);
    public function getLoader();
    public function setActionRepository(
        Zend_Tool_Framework_Action_Repository $actionRepository
    );
    public function getActionRepository();
    public function setProviderRepository(
        Zend_Tool_Framework_Provider_Repository $providerRepository
    );
    public function getProviderRepository();
    public function setManifestRepository(
        Zend_Tool_Framework_Manifest_Repository $manifestRepository
    );
    public function getManifestRepository();
    public function setRequest(Zend_Tool_Framework_Client_Request $request);
    public function getRequest();
    public function setResponse(Zend_Tool_Framework_Client_Response $response);
    public function getResponse();
}

Los diversos objetos que gestiona el registro se tratarán en sus secciones correspondientes.

Las clases que deban tener conocimiento del registro deben implementar Zend_Tool_Framework_Registry_EnabledInterface. Esta interfaz simplemente permite la inicialización del registro en la clase de destino.

interface Zend_Tool_Framework_Registry_EnabledInterface
{
    public function setRegistry(
        Zend_Tool_Framework_Registry_Interface $registry
    );
}

72.3.2. Proveedores

Zend_Tool_Framework_Provider representa el aspecto funcional o de "capacidad" del framework. Fundamentalmente, Zend_Tool_Framework_Provider proporcionará las interfaces necesarias para producir "proveedores", o piezas de funcionalidad de herramientas que se pueden invocar y usar dentro de la cadena de herramientas Zend_Tool_Framework. La naturaleza simplista de implementar esta interfaz de proveedor permite al desarrollador un "punto único" para añadir funcionalidad o capacidades a Zend_Tool_Framework.

La interfaz de proveedor es una interfaz vacía y no impone ningún método (este es el patrón de interfaz marcadora):

interface Zend_Tool_Framework_Provider_Interface
{}

O, si lo desea, puede implementar el Provider base (o abstracto) que le dará acceso al Zend_Tool_Framework_Registry:

abstract class Zend_Tool_Framework_Provider_Abstract
    implements Zend_Tool_Framework_Provider_Interface,
               Zend_Tool_Registry_EnabledInterface
{
    protected $_registry;
    public function setRegistry(
        Zend_Tool_Framework_Registry_Interface $registry
    );
}

72.3.3. Cargadores (Loaders)

El propósito de un Loader es encontrar Providers y archivos de Manifest que contengan clases que implementen Zend_Tool_Framework_Provider_Interface o Zend_Tool_Framework_Manifest_Interface. Una vez que un cargador encuentra estos archivos, los proveedores se cargan en el Repositorio de Proveedores y los metadatos de manifiesto se cargan en el Repositorio de Manifiestos.

Para implementar un cargador, se debe extender la siguiente clase abstracta:

abstract class Zend_Tool_Framework_Loader_Abstract
{

    abstract protected function _getFiles();

    public function load()
    {
        /** ... */
    }
}

El método _getFiles() debe devolver un array de archivos (rutas absolutas). El cargador integrado suministrado con Zend Framework se llama cargador IncludePath. Por defecto, el framework de herramientas utilizará un cargador basado en include_path para encontrar archivos que podrían incluir objetos Provider o Manifest Metadata. Zend_Tool_Framework_Loader_IncludePathLoader, sin ninguna otra opción, buscará archivos dentro del include path que terminen en Mainfest.php, Tool.php o Provider.php. Una vez encontrados, se comprobará (mediante el método load() de Zend_Tool_Framework_Loader_Abstract) si implementan alguna de las interfaces soportadas. Si es así, se instancia una instancia de la clase encontrada, y se añade al repositorio correspondiente.

class Zend_Tool_Framework_Loader_IncludePathLoader
    extends Zend_Tool_Framework_Loader_Abstract
{

    protected $_filterDenyDirectoryPattern = '.*(/|\\\\).svn';
    protected $_filterAcceptFilePattern = '.*(?:Manifest|Provider)\.php$';

    protected function _getFiles()
    {
        /** ... */
    }
}

Como puede ver, el cargador IncludePath buscará en todos los include_paths los archivos que coincidan con $_filterAcceptFilePattern y no coincidan con $_filterDenyDirectoryPattern.

72.3.4. Manifiestos

En resumen, el Manifest contendrá metadatos específicos o arbitrarios que resulten útiles para cualquier proveedor o cliente, además de ser responsable de cargar cualquier proveedor adicional en el repositorio de proveedores.

Para introducir metadatos en el repositorio de manifiestos, todo lo que se debe hacer es implementar la interfaz vacía Zend_Tool_Framework_Manifest_Interface, y proporcionar un método getMetadata() que devuelva un array de objetos que implementen Zend_Tool_Framework_Manifest_Metadata.

interface Zend_Tool_Framework_Manifest_Interface
{
    public function getMetadata();
}

Los objetos de metadatos se cargan (mediante un cargador definido más abajo) en el Repositorio de Manifiestos (Zend_Tool_Framework_Manifest_Repository). Los Manifests se procesarán después de que se hayan encontrado y cargado todos los Providers en el repositorio de proveedores. Esto permitirá que los Manifests creen objetos de Metadata basados en lo que actualmente hay dentro del repositorio de proveedores.

Existen algunas clases de metadatos diferentes que se pueden usar para describir metadatos. La clase Zend_Tool_Framework_Manifest_Metadata es el objeto de metadatos base. Como se puede ver en el siguiente fragmento de código, la clase de metadatos base es bastante ligera y de naturaleza abstracta:

class Zend_Tool_Framework_Metadata_Basic
{

    protected $_type        = 'Global';
    protected $_name        = null;
    protected $_value       = null;
    protected $_reference   = null;

    public function getType();
    public function getName();
    public function getValue();
    public function getReference();
    /** ... */
}

También hay otras clases de metadatos integradas para describir metadatos más especializados: ActionMetadata y ProviderMetadata. Estas clases le ayudarán a describir con más detalle los metadatos específicos de acciones o proveedores, y se espera que la referencia sea una referencia a una acción o a un proveedor, respectivamente. Estas clases se describen en el siguiente fragmento de código.

class Zend_Tool_Framework_Manifest_ActionMetadata
    extends Zend_Tool_Framework_Manifest_Metadata
{

    protected $_type = 'Action';
    protected $_actionName = null;

    public function getActionName();
    /** ... */
}

class Zend_Tool_Framework_Manifest_ProviderMetadata
    extends Zend_Tool_Framework_Manifest_Metadata
{

    protected $_type = 'Provider';
    protected $_providerName  = null;
    protected $_actionName    = null;
    protected $_specialtyName = null;

    public function getProviderName();
    public function getActionName();
    public function getSpecialtyName();
    /** ... */
}

El 'Type' en estas clases se utiliza para describir el tipo de metadatos del que es responsable el objeto. En el caso de ActionMetadata, el tipo sería 'Action', y, a la inversa, en el caso de ProviderMetadata el tipo es 'Provider'. Estos tipos de metadatos también incluirán información estructurada adicional tanto sobre la "cosa" que están describiendo como sobre el objeto (el getReference()) al que hacen referencia con estos nuevos metadatos.

Para crear su propio tipo de metadatos, todo lo que se debe hacer es extender la clase base Zend_Tool_Framework_Manifest_Metadata y devolver estos nuevos objetos de metadatos a través de una clase u objeto Manifest local. Estas clases basadas en el usuario vivirán en el Repositorio de Manifiestos

Una vez que estos objetos de metadatos están en el repositorio, hay entonces dos métodos diferentes que se pueden usar para buscarlos en el repositorio.

class Zend_Tool_Framework_Manifest_Repository
{
    /**
     * To use this method to search, $searchProperties should contain the names
     * and values of the key/value pairs you would like to match within the
     * manifest.
     *
     * For Example:
     *     $manifestRepository->findMetadatas(array(
     *         'action' => 'Foo',
     *         'name'   => 'cliActionName'
     *         ));
     *
     * Will find any metadata objects that have a key with name 'action' value
     * of 'Foo', AND a key named 'name' value of 'cliActionName'
     *
     * Note: to either exclude or include name/value pairs that exist in the
     * search criteria but do not appear in the object, pass a bool value to
     * $includeNonExistentProperties
     */
    public function findMetadatas(Array $searchProperties = array(),
                                  $includeNonExistentProperties = true);

    /**
     * The following will return exactly one of the matching search criteria,
     * regardless of how many have been returned. First one in the manifest is
     * what will be returned.
     */
    public function findMetadata(Array $searchProperties = array(),
                                 $includeNonExistentProperties = true)
    {
        $metadatas = $this->getMetadatas($searchProperties,
                                         $includeNonExistentProperties);
        return array_shift($metadatas);
    }
}

Observando los métodos de búsqueda anteriores, las firmas permiten una búsqueda extremadamente flexible. Para encontrar un objeto de metadatos, simplemente pase un array de restricciones de coincidencia mediante un array. Si se puede acceder a los datos a través del accesor de Propiedad (los métodos getSomething() implementados en el objeto de metadatos), entonces se devolverá al usuario como un objeto de metadatos "encontrado".

72.3.5. Clientes

Los Clients son la interfaz que conecta a un usuario o herramienta externa con el sistema Zend_Tool_Framework. Los Clients pueden presentarse en todas las formas y tamaños: puntos finales RPC, Interfaz de Línea de Comandos, o incluso una interfaz web. Zend_Tool ha implementado la interfaz de línea de comandos como la interfaz predeterminada para interactuar con el sistema Zend_Tool_Framework.

Para implementar un cliente, sería necesario extender la siguiente clase abstracta:

abstract class Zend_Tool_Framework_Client_Abstract
{
    /**
     * This method should be implemented by the client implementation to
     * construct and set custom loaders, request and response objects.
     *
     * (not required, but suggested)
     */
    protected function _preInit();

    /**
     * This method should be implemented by the client implementation to parse
     * out and set up the request objects action, provider and parameter
     * information.
     */
    abstract protected function _preDispatch();

    /**
     * This method should be implemented by the client implementation to take
     * the output of the response object and return it (in an client specific
     * way) back to the Tooling Client.
     *
     * (not required, but suggested)
     */
    abstract protected function _postDispatch();
}

Como puede ver, se requiere 1 método para satisfacer las necesidades de un cliente (se sugieren otros dos), la inicialización, el prehandling y el posthandling. Para un estudio más detallado de cómo funciona el cliente de línea de comandos, consulte el código fuente.