lunes, 4 de mayo de 2009

Zend_Application and Autoload Modules

UPDATE: if you're using SVN, you need to update to a later revision (after 15357, mandatory) due to a bug

La liberación de la versión 1.8 del Zend Framework deja mucho que desear en cuanto a documentación. Erratas y omisiones parecen ser los principales problemas con los que nos encontramos los usuarios. Además, no se ha publicado el API 1.8 para su descarga (sólo consulta online). Sin embargo, los test sobre el código cubren el 100% y hacen más llevadera la interpretación del código.

Otro de los problemas con el que nos encontramos es cómo configurar nuestra aplicación modular para que se beneficie del componente Zend_Application y la carga dinámica de los recursos mediante Zend_Application_Module_Bootstrap. Por eso hemos decidido escribir este post y ofrecer como ejemplo una sencilla aplicación modular que se representa en el siguiente árbol:

En primer lugar creamos nuestro public/index.php

// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));

// Ensure library is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(dirname(__FILE__) . '/../library'),
get_include_path()
)));

/* Zend_Application */
require_once 'Zend/Application.php';

// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap()->run();

A continuación añadimos los datos de configuración de nuestra aplicación en: /application/configs/application.ini

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0

bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"

autoLoaderNameSpaces.0 = "Scienta"

resources.layout.layout = "layout"
resources.layout.layoutPath = APPLICATION_PATH "/layout/scripts"

resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.plugins.debug = "Scienta_Controller_Plugin_Debug"


resources.modules[] =

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

En tercer lugar, acondicionamos nuestro /application/Bootstrap.php



class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/**
* @var Zend_Log
*/
protected $_logger;

protected function _initLogging()
{
$this->bootstrap('frontcontroller');
$logger = new Zend_Log();

$writer = 'production' == $this->getEnvironment() ?
new Zend_Log_Writer_Stream(APPLICATION_PATH . '/../var/logs/app.log') :
new Zend_Log_Writer_Firebug();
$logger->addWriter($writer);

if ('production' == $this->getEnvironment()) {
$filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT);
$logger->addFilter($filter);
}

if($writer instanceof Zend_Log_Writer_Firebug)
{
$writer-> setPriorityStyle(8, 'TABLE');
$logger->addPriority('TABLE', 8);
}


$logger->info($this->bootstrap('frontcontroller'));
$logger->info($this->getPluginResourceNames());
$logger->info($this->getApplication());
Zend_Registry::set('logger', $logger);

/*
* Set _logger for use with other methods
*/
$this->_logger = $logger;
}
protected function _initView()
{
// Initialize view
$view = new Zend_View();
$view->doctype('XHTML1_STRICT');
$view->headTitle('My First Zend Framework Application');
// set the content type and language
$view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8');
$view->headMeta()->appendHttpEquiv('Content-Language', 'en-US');

$view->headLink()->appendStylesheet('/css/basic.css');
$view->headLink()->appendStylesheet('/css/jquery-ui-themeroller.css');

// Add it to the ViewRenderer
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer'
);
$viewRenderer->setView($view);

// Return it, so that it can be stored by the bootstrap
return $view;
}

}


Y, finalmente, en cada uno de nuestros módulos, añadimos un archivo que instancie el module bootstrap:



Puedes descargar el código fuente de este pequeño ejemplo aquí:

Download Source Code.

viernes, 1 de mayo de 2009

Liberada la versión 1.8 del Zend Framework




El Zend Framework 1.8 acaba de ser publicado esta noche y está disponible para su descarga.

Se trata casi de una actualización mayor, ya que, por un lado, empieza a romper la compatilidad con versiones previas y se empieza a enfilar la versión 2.0 (el método estático Zend_Loader::registerAutoload ha sido marcado como deprecated y sustituido por la funcionalidad del nuevo componente Zend_Loader_Autoloader) y, por otro, porque la funcionalidad de algunos de los nuevos componentes intenta superar la brecha que existe entre lo que se conoce como glue framework vs Full Stack framework, es decir, incorporar elementos de autosuficiencia que permitan usarlo como entorno completo de desarrollo.

Así, se incorporan las siguientes novedades que nos parecen interesantes:
  • La herramienta de comandos Zend_Tool, para crear y editar proyectos desde la linea de comandos y aliviarnos del trabajo que supone tener que crear a mano toda la estructura del proyecto.
  • Zend_Application, el componente que permite configurar el Bootstrap de la aplicación de una forma orientada a objetos.
  • Zend_Navigation, una forma sencilla de tratar menús, breadcrumbs o sitemaps.
  • Zend_Json mejorado para soportar expresiones.
Para una descripción completa de las notas de la versión, se puede consultar el post de Matthew Weier O'Phinney (Nuevo jefe de proyecto -y el más cualificado, por cierto-) en Devzone