Aplicación demo en Zend Framework
La siguiente demo se ha desarrollado bajo:
- Zend Framework 1.9.3
- PHP 5.3.0
- Apache 2.2.11
Lo almacenaremos en una tabla sencilla como la siguiente:
| Atributo | Tipo | Obligatorio | Comentarios |
| Id | Integer | Si | CP y autoincremento |
| título | varchar(100) | Si | |
| autor | varchar(100) | Si |
- Home: Página desde la que podremos ver el listado total de libros de nuestra biblioteca
- Añadir nuevo libro: Vista que nos permitirá dar de alta un nuevo libro
- Editar libro: Vista desde la que podremos modificar los datos de cualquier libro de nuestra biblioteca
- Eliminar un libro: Vista desde la que podremos eliminar cualquier libro que haya en nuestra biblioteca
El directorio /application es donde residirá el código de nuestra aplicación web. Como se puede ver, tenemos separados en directorios distintos tanto la vista, como el modelo como los controladores.
El directorio /public es el que será la raíz de nuestra aplicación web, por lo que para acceder a la aplicación en nuestro navegador deberemos poner: http://localhost/Biblioteca/public.
Para un portal público, se podría crear un host virtual haciendo que el document root sea directamente el directorio /public. Por ejemplo, podemos crear el host virtual llamado biblioteca.localhost de la siguiente manera en el fichero http-vhosts.conf.
Si nuestro Apache está escuchando por el puerto 80:
<VirtualHost *:80>
ServerName biblioteca.localhost
DocumentRoot /var/www/html/biblioteca/public
<Directory "/var/www/html/biblioteca/public">
AllowOverride All
</Directory>
</VirtualHost>
Si nuestro Apache está escuchando por el Puerto 8080:
<VirtualHost *:8080>
ServerName biblioteca.localhost:8080
DocumentRoot /var/www/html/biblioteca/public
<Directory "/var/www/html/biblioteca/public">
AllowOverride All
</Directory>
</VirtualHost>
Si nuestro sistema operativo es windows, deberemos dar de alta la url de acceso http://bibioteca.localhost en el archive hosts c:\windos\system32\drivers\etc\hosts. Se le debe asociar la IP 127.0.0.1 a http://biblioteca.localhost en el archivo hosts.
Las imágenes, los archivos de javascript y css de nuestra aplicación irán almacenados en directorios, dentro del directorio /public.
Ahora validaremos que nuestra aplicación se puede ver a través de la URL http://biblioteca.localhost:8080 y … ¡¡¡Voilà!!!
Cuando creamos el proyecto, se nos crea por defecto, dentro del directorio /application la clase Bootstrap que hereda de Zend_Application_Boostrap_Boostrap la cual nos permitirá poner en ella todo el código que sea necesario para el inicio de nuestra aplicación.
Fichero de configuración
El proyecto, dispone de un fichero de configuración propio en /application/configs con nombre application.ini que nos permite establecer los valores de configuración de la aplicación según el entorno en el que nos encontremos, pudiendo ser estos:
- Producción
- Test
- Desarrollo
phpSettings.date.timezone = "UTC" Evidentemente, podemos utilizar cualquier configuración horaria. Aquí tenemos un listado de zonas horarias de todo el mundo Crear autoloading
Necesitamos crear un autoloading que cargue con todos los parámetros necesarios para la aplicación, nada más inicilizarse. El código donde se implementa esta carga es en la clase Bootstrap. El método que añadamos debe tener como prefijo _init. De esta manera se le indica a Zend Framework que debe llamar a dicha función para inicializar la aplicación. /application/Bootstrap.php
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{
protected function _initAutoload(){
$moduleLoader = new Zend_Application_Module_Autoloader(array('namespace' => '', 'basePath' => APPLICATION_PATH));
return $moduleLoader;
}
}
?>
El módulo autoloader cargará clases con un determinado prefijo que se encontrarán dentro del directorio /application, según la siguiente tabla:
| Directorio | Prefijo | Ejemplo |
| api | Api_ | Api_Rest |
| forms | Form_ | Form_Login |
| models | Model_ | Model_Libros |
| models/DbTable | Model_DbTable_ | Model_DbTable_Libros |
| plugins | Plugin_ | Plugin_ |
- Crear controladores
- Crear modelos
- Crear base de datos
- Implementar cada una de las acciones de nuestra aplicación:
- Listado de libros
- Añadir nuevo libro
- Editar un libro
- Borrar un libro
Antes de empezar a añadir código, es necesario especificar que cada página de la aplicación es conocida como una “acción” y que las acciones están agrupadas en “controladores” (controllers). Esto permite agrupar un conjunto de acciones relacionadas entre ellas. Por ejemplo, un “controlador” de Libros al que podemos llamar “libros”, podría tener las acciones de listado de libros, archivo de libros y visualización de información de un libro en concreto, por ejemplo.
Por defecto, los controladores en Zend Framework tienen una acción definida por defecto, denominada index de manera que para el caso anterior de las noticias podríamos tener que a través de http://biblioteca.localhost:8080/libros el cual nos daría la acción index que se haya definido. Hay que añadir, que Zend Framework dispone de un nombre de controlador por defecto cuyo nombre no puede ser modificado y que es llamado index, el cual ejecutará por defecto la acción index. La url desde la que será llamado dicho controlador index será http://biblioteca.localhost:8080/ Ya estamos en disposición de listar los controladores y las acciones asociadas a estos que vamos a tener en nuestra aplicación de prueba:| Página | Controlador | Acción |
| Home | Index | index |
| Añadir libro | Libro | anyadir |
| Editar libro | Libro | editar |
| Borrar libro | Libro | borrar |
En Zend Framework los nombres de los controladores comienzan con una letra mayúscula seguida del nombre Controller, es decir, el nombre de la clase sería NombreControlador, y esta se encontraría dentro de un archivo con el nombre NombreControladorController.php dentro del directorio /application/controllers. Cada acción es un método público de la clase definida anteriormente y su nombre será escrito en minúsculas seguido de “Action”, es decir, nombreaccionAction. La creación de los controladores la podemos hacer de dos maneras:
- A través de la consola de comandos
- A través de Zend Studio 7.0
- Creación de un nuevo controlador: zf create controller Libro
- Creación de la acción “anaydir”: zf create action añadir Libro
- Creación de la acción “editar”: zf create action editar Libro
- Creación de la acción “borrar”: zf create action borrar Libro
Hacemos clic sobre el directorio /controllers con el botón derecho, seleccionamos New / Zend FrameworkItem.
Seleccionamos Zend Controller (Template Based) y pulsamos “Next”.
Indicamos el nombre de nuestro nuevo controller, LibroController.php.
Pulsamos “Next” e indicamos el template que utilizaremos para crear el controlador “New Zend Controller”.
Pulsamos “Finish” y se nos creará el controlador en el directorio /controllers. A partir de aquí, añadir las acciones al controlador, es tan sencillo como añadir los métodos públicos que implementen dichas acciones con la nomenclatura especificada anteriormente.
Una vez creados nuestros controladores y sus acciones, las urls desde las que se tendrá acceso a ellos será:
| URL | Método Action |
| http://biblioteca.localhost:8080/ | IndexController::indexAction() |
| http://biblioteca.localhost:8080/Libro/anyadir | LibroController::anyadirAction() |
| http://biblioteca.localhost:8080/Libro/editar | LibroController::editarAction() |
| http://biblioteca.localhost:8080/Libro/borrar | LibroController::borrarAction() |
Una vez definidos los controladores, estamos en disposición de definir las reglas de negocio en las que está basada nuestra aplicación. Estas reglas de negocio son lo que constituyen el Modelo, y estás están basadas en los datos que se encuentran en nuestra base de datos. Los datos de acceso a nuestra base de datos se lo daremos a la aplicación a trav&eacutre;s del archivo de configuración application.ini, siendo la siguiente:
resources.db.adapter = PDO_MYSQL resources.db.params.host = localhost resources.db.params.username = usuario_base_de_datos resources.db.params.password = contraseña_base_de_datos resources.db.params.dbname = nombre_base_de_datosCreamos la base de datos con la siguiente sentencia:
create table libros ( id int(11) NOT NULL auto_increment, titulo varchar(100) NOT NULL, autor varchar(100) NOT NULL, PRIMARY KEY (id) );Insertamos algunos libros en nuestra base de datos:
insert into libros (titulo, autor) values (‘El guardian entre el centeno’, ‘J.D. Salinger’); insert into libros (titulo, autor) values (‘Todos los hombres del presidente’, ‘Robert Penn Warren’); insert into libros (titulo, autor) values (‘El señor de los anillos’, ‘J.R.R. Tolkien’); insert into libros (titulo, autor) values (‘Crónicas Marcianas’, ‘Ray Bradbury’); insert into libros (titulo, autor) values (‘El jugador’, ‘Fiodor Dostoievsky’);
El Modelo
Zend Framework facilita la clase Zend_Db_Table la cual permite acceder a los datos que se encuentra en la Base de Datos. Para proyectos de mayor envergadura, se suelen crear una o más instancias de la clase Zend_Db_Table, para nuestro ejemplo, con una es suficiente. Zend_Db_Table es una clase abstracta, por lo que tenemos que crear una que herede de ella. El nombre que tendrá, vendrá definida por el prefijo Model_DbTable_ y el nombre de la tabla con la que se va a interactuar, nombre que además informaremos en la variable protegida $_name. Zend_Db_Table asume que nuestra tabla tiene una clave primaria que se llama id y que este es un auto incremental. El nombre de la clave primaria se puede modificar si así se desea. Nuestra nueva clase la crearemos en el archivo Libros.php, dentro de /applications/models/DbTable/Libros.php Plantillas y Vistas El componente de Zend Framework que da soporte a las vistas es Zend_View. Este nos permite separar la presentación de la lógica o reglas de negocio que se encuentra en el modelo. En Zend Framework encontramos las vistas en el directorio “views” y se organizan de la forma: views/scripts/{nombredelcontrolador}/{nombredelaaccion}.phtml. Como os habréis dado cuenta nuestras vistas ya están creadas (ocurrió cuando creamos los controladores), ahora corresponde que nos ocupemos del “layout”. En la mayoría de los proyectos hay partes de código HTML que se repite para todas las vistas, por ejemplo: un encabezado, una columna lateral y el pie de página. Para evitar repetir código es que existe la posibilidad de crear un “layout” o plantilla donde colocaremos el código común y desde donde llamaremos las vistas. Lo primero que debemos hacer es crear el directorio: “application/layouts/” y agregar en nuestro archivo de configuración la siguiente línea:resources.layout.layoutpath = APPLICATION_PATH “/layouts”Esta línea la colocamos dentro de la sección [production] del archivo de configuración de la aplicación.
Además, necesitamos inicializar nuestra vista en la clase Boostrap, para lo que crearemos otros métodos que comiencen por el prefijo _init justo debajo de _initAutoload(). El método se llamará _initViewHelpers()
protected function _initViewHelpers(){
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();
$view->doctype('XHTML1_STRICT');
$view->headMeta()->appendHttpEquiv('Content-Type', 'text/html;charset=utf-8');
$view->headMeta()->appendHttpEquiv('Cache-Control', 'no-cache');
$view->headTitle()->setSeparator(' - ');
$view->headTitle('Biblioteca');
Zend_Session::start();
}
A través del método bootstrap() inicializamos la vista para cuando después recuperemos el objeto Zend_Layout a través de getResource(), para después recuperar la vista utilizando el método getView().
Una vez que tenemos la vista instanciada, podemos llamar a varios métodos de ayuda de la vista, que definirán en nuestra vista el código correspondiente para cada uno de ellos.
Por ejemplo, en nuestro ejemplo definimos como métodos de ayuda para nuestra vista:
- doctype
- headMeta
- headTitle
<?php echo $this->doctype(); ?> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <?php echo $this->headMeta(); ?> <?php echo $this->headTitle(); ?> </head> <body> <div id="content"> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->layout()->content; ?> </div> </body> </html>En el código de nuestra página, vemos como tenemos una instancia del objeto de la vista a través de $this, por lo que podemos utilizar esta instancia para llamar a los métodos asociados a la vista y recuperar información que le ha sido asignada a la vista. Una vez hechos estos cambios y añadido nuestro “layout”, podemos validar cómo se ve la vista en estos momentos, y podemos ver que es la misma que al inicio, pero ahora está servida por nuestro layout. Lo podemos ver en el título de la página que es el que le hemos dado el layout.
Estilos
Para la versión de Zend Framework 1.9 se tiene un método de ayuda llamado baseURL() correspondiente a la vista y que nos facilita la url donde se encuentra la raíz del proyecto, para ello, deberemos implementar un método de ayuda en la vista.
Creamos un archivo en /application/Views/helpers/BaseUrl.php. Este método se encontrará dentro de la clase Zend_View_Helper_{HelperName}. Creamos el archivo BaseUrl.php y le añadimos el código:
class Zend_View_Helper_BaseUrl{
public function baseUrl(){
//Definimos la url base de la aplicación
$url = Zend_Controller_Front::getInstance()->setBaseUrl("http://biblioteca.localhost:8080/");
//Devolvemos la url base de la aplicación
return $url->getBaseUrl();
}
}
Una vez creado este método en el archivo /application/Views/helpers/BaseUrl.php podemos crear el CSS (biblioteca.css) con todos los estilos:
body,html {
margin: 0 5px;
font-family: Verdana,sans-serif;
}
h1 {
font-size: 1.4em;
Page 11 of 18
color: #008000;
}
a {
color: #008000;
}
/* Table */
th {
text-align: left;
}
td, th {
padding-right: 5px;
}
/* style form */
form dt {
width: 100px;
display: block;
float: left;
clear: left;
}
form dd {
margin-left: 0;
float: left;
}
form #submitbutton {
margin-left: 100px;
}
Este archivo va en la siguiente ruta /application/public/css/biblioteca.css
La llamada a este archivo, la podemos hacer en el archivo "layout.phtml" una vez creado el archivo, y definido el método de ayuda que nos facilitará la url de la raíz de nuestra aplicación. Para ello, añadimos una línea a nuestro código que haga la llamada al archivo .css de la siguiente manera:
<head> <?php echo $this->headMeta()."\n"; ?> <?php echo $this->headTitle()."\n"; ?> <?php echo $this->headLink()->prependStylesheet($this->baseUrl()."/css/biblioteca.css")."\n"; ?> </head>
| Página | Controlador | Acción |
| Home | Index | index |
| Añadir libro | Libro | index |
| Editar libro | Libro | editar |
| Borrar libro | Libro | borrar |
public function indexAction(){
//Título de la vista
$this->view->title = "Mis Libros";
//Añadimos el título a la vista
$this->view->headTitle($this->view->title, 'PREPEND');
//Creamos el modelo, para la consulta de libros
$libros = new Model_DbTable_Libros();
//Devolvemos a la vista todos los libros
$this->view->libros = $libros->fetchAll();
}
fetchAll() es una función de Zend_Db_Table_Rowset que nos permite interactuar sobre las filas devueltas en la consulta. Ahora ya estamos en disposición de crear el código del archivo /application/views/scripts/index/index.phtml
<p><a href="<?php echo $this->url
(array('controller'=>'libro','action'=>'add'));?>">
Añadir nuevo libro</a></p>
<table>
<tr>
<th>Título</th>
<th>Autor</th>
<th> </th>
</tr>
<?php foreach($this->libros as $libro) : ?>
<tr>
<td><?php echo $this->escape($libro->titulo);?></td>
<td><?php echo $this->escape($libro->autor);?></td>
<td>
<a href="<?php echo $this->url
(array('controller'=>'libro', 'action'=>'update', 'id'=>$libro->id));?>">Editar</a>
<a href="<?php echo $this->url(array('controller'=>'libro', 'action'=>'delete', 'id'=>$libro->id));?>">Borrar</a>
</td>
</tr>
<?php endforeach; ?>
</table>
La ejecución del código anterior, nos da como resultado la página principal de nuestra aplicación donde vemos nuestro listado de libros de la biblioteca:
Añadir nuevos libros
Para poder añadir nuevos libros en nuestra biblioteca, necesitamos realizar las siguientes acciones:
- Crear un nuevo formulario
- Tratar los datos recibidos del formulario anterior e insertarlos en BBDD
Para la creación del formulario, utilizaremos Zend_Form, quien nos permite crear un formulario, y validar los datos de entrada del formulario. Crearemos la clase Form_Libro que heredará de Zend_Form para definir nuestro formulario.
Creamos el archivo Libro.php en /application/forms/Libro.php
<?php
class Form_Libro extends Zend_Form{
public function __construct($options = null){
parent::__construct($options);
$this->setName('libro');
$id = new Zend_Form_Element_Hidden('id');
$autor = new Zend_Form_Element_Text('autor');
$autor->setLabel('Autor')
->setRequired(true)
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('NotEmpty');
$titulo = new Zend_Form_Element_Text('titulo');
$titulo->setLabel('Titulo')
->setRequired(true)
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('NotEmpty');
$submit = new Zend_Form_Element_Submit('submit');
$submit->setAttrib('id', 'submitbutton');
$this->addElements(array($id, $autor, $titulo, $submit));
}
}
?>
Dentro del constructor, especificamos los dos campos que son necesarios para dar de alta un nuevo libro en nuestra biblioteca: autor y título, así como el botóe;n a través del cual desencadenaremos la validación de datos y el envío de estos a nuestro servidor. Para los campos, hemos añadido dos filtros “StripTags” y “StringTrim” que eviten la introducción de código HTML o de espacios en blanco no deseables. Además, los hemos definido como no vacíos.
A partir de ahora debemos mostrar el formulario, y tratar los datos recibidos desde el, acciones que se realizar´n en el Controlador LibroController dentro del método anyadirAction()
En /application/controllers/LibroController.php añadimos el siguiente código:
public function anyadirAction(){
//Indicamos el título de la página
$this->view->title = "Añadir nuevo libro";
//Añadimos el título, delante del título definido por defecto para nuestra aplicación
$this->view->headTitle($this->view->title, 'PREPEND');
//Instanciamos el formulario
$form = new Form_Libro();
//Especificamos el nombre del botón de envío del formulario
$form->submit->setLabel('Añadir');
//Asignamos a la vista el formulario
$this->view->form = $form;
if ($this->getRequest()->isPost()){ //Si se envían los datos, los recuperamos del formulario
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)){ //Validamos que los datos recibidos sean correctos
//Asignamos los valores recuperados a variables
$autor = $form->getValue('autor');
$titulo = $form->getValue('titulo');
//Creamos el modelo
$libros = new Model_DbTable_Libros();
//Insertamos el nuevo libro en nuestra BBDD
$libros->addLibro($titulo, $autor);
//Redireccionamos a la home, donde podremos ver el nuevo libro introducido.
$this->_redirect('/');
}else{ //Si los datos del formulario, no son válidos, se muestra el formulario con los datos de nuevo.
$form->populate($formData);
}
}
}
[php]<p />
Para finalizar, nos queda hacer que el formulario salga, renderizarlo, para ello, crearemos el script a&ntidel;adir.phtml en /application/views/scripts/libro/anyadir.phtml<p />
[php]
<?php echo $this->form ;?>
Si validamos la nueva funcionalidad, veremos cómo finalizamos al final del proceso en la home de la aplicación, con nuestro nuevo libro introducido en la biblioteca.
Editar un libro
Editar un libro es muy parecido a añadir un libro. Comenzaremos implementando la acción correspondiente de nuestro controlador. En este caso la acción “editar” de nuestro controlador “Libro”.Añadimos el siguiente código en /application/controllers/LibroController.php
[/php]
public function editarAction(){
//Indicamos el título de la página
$this->view->title = "Editar Libro";
//Añadimos el título, delante del título definido por defecto para nuestra aplicación
$this->view->headTitle($this->view->title, 'PREPEND');
//Instanciamos el formulario
$form = new Form_Libro();
//Especificamos el nombre del botón de envío del formulario
$form->submit->setLabel('Guardar');
//Asignamos a la vista el formulario
$this->view->form = $form;
if ($this->getRequest()->isPost()) {//Si se envían los datos, los recuperamos del formulario
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {//Validamos que los datos recibidos sean correctos
//Asignamos los valores recuperados a variables
$id = (int)$form->getValue('id');
$autor = $form->getValue('autor');
$titulo = $form->getValue('titulo');
//Creamos el modelo
$libros = new Model_DbTable_Libros();
//Actualizamos los datos del libro
$libros->updateAlbum($id, $autor, $titulo);
//Vamos a la página principal de la aplicación
$this->_redirect('/');
}else{//Si los datos del formulario, no son válidos, se muestra el formulario con los datos de nuevo.
$form->populate($formData);
}
}else{//Mostramos los datos del libro en caso de no haber enviado los datos al servidor para actualizar el libro
$id = $this->_getParam('id', 0);
if ($id > 0) {
$albums = new Model_DbTable_Libros();
$form->populate($albums->getAlbum($id));
}
}
}
[php]
La principal diferencia la tenemos en el momento en el que se sirve el formulario, sin haber recibido los datos previamente del formulario, donde se recuperan los datos del libro seleccionado y se muestran estos para su actualización.
Para finalizar, nos queda hacer que el formulario salga, renderizarlo, para ello, crearemos el script añadir.phtml en /application/views/scripts/libro/editar.phtml
<?php echo $this->form ;?>Si hacemos un test, y modifcamos el título de “El jugador”, por “El Jugador”, podemos ver finalmente la vista a la que regresamos como quedaría:
Guardamos el libro, y comprobamos la modificación del título del libro:
El título, “El Jugador” ha sido cambiado pasando la “j” a mayúsculas en la vista anterior.
Borrar un libro
Para finalizar nuestra aplicación, necesitamos poder borrar un libro de nuestra biblioteca. Desde un principio, tenemos asociado a cada libro, un enlace que nos lleva a borrar un libro, pero antes de realizar el borrado, lo que haremos será solicitar una confirmación de la acción.
Cuando se pulse el enlace “Borrar”, se desencadenará la acción definida en el método borrarAction() de nuestro controlador LibroController.
En /application/controllers/LibroController.php añadimos el siguiente código:
public function borrarAction(){
$this->view->title = "Borrar libro";
$this->view->headTitle($this->view->titulo, 'PREPEND');
if ($this->getRequest()->isPost()) {
$del = $this->getRequest()->getPost('del');
if ($del == 'Yes') {
$id = $this->getRequest()->getPost('id');
$libros = new Model_DbTable_Libros();
$libros->deleteLibro($id);
}
$this->_redirect('/');
}else{
$id = $this->_getParam('id', 0);
$libros = new Model_DbTable_Libros();
$this->view->libro = $libros->getLibro($id);
}
}
Al igual que en los formularios de añadir y editar un libro, utilizamos el método isPost() para diferenciar si lo que estamos haciendo es mostrar la información recuperada en caso de ser false o para realizar la acción definida si es true.
Ahora, ya podemos crear la vista del formulario, tal y como se expone a continuación:
Creamos el archivo borrar.phtml en /application/views/scripts/libro e insertamos el siguiente código:
<p>¿Estás seguro que quieres borrar el libro
'<?php echo $this->escape($this->libro['titulo']); ?>' por
'<?php echo $this->escape($this->libro['autor']); ?>'?
</p>
<form action="<?php echo $this->url(array('action'=>'borrar')); ?>" method="post">
<div>
<input type="hidden" name="id" value="<?php echo $this->libro['id']; ?>" />
<input type="submit" name="del" value="Si" />
<input type="submit" name="del" value="No" />
</div>
</form>
A partir de aquí, si pulsamos “Si” procederemos a su borrado, y si es “No”, volveremos a nuestro listado de libros.
Descarga de código fuente de la Aplicación demo en Zend Framework
¡¡¡Y esto es todo para tener nuestra biblioteca en completo funcionamiento!!!
21 octubre, 2011 - 11:29
@Jaime
Hola, muchas gracias por tus comentarios.
Salu2,
José Carlos
22 octubre, 2011 - 06:10
A la verdad que aprender Zend es casi aprender otro lenguaje de programacion, recomiendo CI (CodeIgniter) para principiantes en esto de MVC.
CI para proyectos de cualquier calibre.
Saludos, desde R.D.