Comenzando con Zend Framework: IV Parte
Por zsamer en Abril 18, 2008
Retomando el último post del set de artículos "Comenzando con Zend Framework", hoy vamos a ver cómo podemos tener acceso a las tablas de la base de datos para que nuestro sistema sea bastante más interesante. Mi idea, es desarrollar un sistema de comentarios, simple pero útil.
También vamos a ver como implementar en nuestro sistema el componente de configuración que trae ZF llamado Zend_Config, diseñado para tener fácil acceso y usar un archivo de configuración con nuestra aplicación y de esa manera obtener ciertos parámetros fundamentales, tales como el nombre de la base de datos, adaptador o motor, usuario, password y otros parámetros más como por ejemplo el nombre de nuestra aplicación. Además provee funcionalidades muy potentes, entre ellas se destaca el manejo jerarquía de datos, un ejemplo podría ser los recursos de nuestra aplicación para el manejo de Listado de Control de Acceso (ACL) que podríamos implementar con Zend_ACL.
Actualmente Zend_Config ofrece adaptadores de los datos de configuración que se almacenan en archivos de texto con Zend_Config_Ini y archivos XML con Zend_Config_Xml.
En nuestro ejemplo vamos a utilizar a Mysql como nuestro motor de base de datos para guardar los comentarios y luego mostrarlos.
La definición o estructura de las tablas en la base de datos quickstart sería (tienen que crearla con usuario y password "test"):
-
--
-
-- Base de datos: `quickstart`
-
--
-
-
-- --------------------------------------------------------
-
-
--
-
-- Estructura de tabla para la tabla `comments`
-
--
-
-
DROP TABLE IF EXISTS `comments`;
-
CREATE TABLE IF NOT EXISTS `comments` (
-
`comment_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-
`comments` TEXT NOT NULL,
-
PRIMARY KEY (`comment_id`)
-
) ENGINE=MyISAM;
Ahora demos una previa repasada de Zend_Db, sus clases proporcionan una poderosa interfaz de abstracción de base de datos SQL. Zend_Db_Adapter es la clase básica que se utiliza para conectar nuestra aplicación a un RDBMS. Hay una clase diferente de adaptadores para cada tipo de RDBMS, entre ellas tenemos Mysql, Oracle, MSSQL, IBM DB2, PostgreSQL Y SQLite.
Veamos un ejemplo de conexión a Mysql:
-
require_once 'Zend/Db.php';
-
-
// Automaticalmente carga la clase Zend_Db_Adapter_Pdo_Mysql y crea una instancia de esta.
-
'host' => 'localhost',
-
'username' => 'test',
-
'password' => 'test',
-
'dbname' => 'quickstart '
-
));
Como se puede ver ya se ve algo interesant, se está implementando el patrón de diseño Factory, nosotros le indicamos el adaptador mediante un string pasado en el método, en nuestro caso 'Pdo_Mysql' y nos retorna el objeto del adaptador (Zend_Db_Adapter_Abstract) correspondiente para el acceso y manejo de los datos.
Ahora bien, necesitamos el archivo de configuración para nuestro ejemplo vamos a usar el archivo de texto INI:
quickstart/application/config/quickstart.ini
-
; Quickstart configuration data
-
[default]
-
;database
-
database.adapter = pdo_mysql
-
database.params.host = localhost
-
database.params.dbname = quickstart
-
database.params.username = test
-
database.params.password = test
Ahora tenemos que hacer ciertos cambios a nuestro index.php (puerta de entrada al sistema), quedando de la siguiente forma:
quickstart/public/index.php
-
<?php
-
-
/** Seteo y Configuración de Directorios */
-
-
$rootPath . '/application/config' . PATH_SEPARATOR .
-
$rootPath . '/application/models' . PATH_SEPARATOR .
-
$rootPath . '/library' . PATH_SEPARATOR .
-
$rootPath . '/public');
-
-
/** Carga el archivo de configuración ini */
-
require_once 'Zend/Config/Ini.php';
-
$config = new Zend_Config_Ini('quickstart.ini', 'default');
-
-
/** Base de Datos */
-
require_once 'Zend/Db.php';
-
require_once 'Zend/Db/Table/Abstract.php';
-
$db = Zend_Db::factory($config->database);
-
Zend_Db_Table_Abstract::setDefaultAdapter($db);
-
-
require_once 'Zend/Controller/Front.php';
-
$frontController = Zend_Controller_Front::getInstance();
-
$frontController->setControllerDirectory($rootPath . '/application/controllers')
-
->throwExceptions(true)
-
->dispatch();
Como se puede observar nuestro index ha crecido bastante en comparación a como estaba antes, y nuestra aplicación cada ves va tomando más forma y se hace más robusta.
No hay mucho más que comentar de nuestro nuevo index salvo mencionar que Zend_Db_Table_Abstract::setDefaultAdapter($db) nos guarda nuestro objeto de base de datos de forma estática lo cual nos permitirá después hacer uso de ella en cualquier parte de nuestro sistema mediante Zend_Db_Table_Abstract::getDefaultAdapter();
Hemos avanzado harto, pero todavía falta su resto, definamos nuestra clase Modelo CommentsTable, ubicada dentro de la carpeta application/models/ de nuestra aplicación:
quickstart/application/models/CommentsTable.php
-
<?php
-
require_once 'Zend/Db/Table/Abstract.php';
-
class CommentsTable extends Zend_Db_Table_Abstract
-
{
-
protected $_name = 'comments';
-
protected $_primary = 'comment_id';
-
{
-
require_once 'Zend/Form.php';
-
'method' => 'post',
-
'required' => true,
-
'label' => 'Write your comments'
-
)),
-
'label' => 'Send'
-
))
-
),
-
));
-
return $form;
-
}
-
{
-
$commentsTable = new CommentsTable();
-
return $commentsTable->fetchAll();
-
}
-
{
-
$commentsTable = new CommentsTable();
-
$comment = $commentsTable->createRow($data);
-
$comment->save();
-
}
-
}
Nuestra clase modelo extiende a la clase Zend_Db_Table_Abstract, esta última implementa un conocido patrón de diseño llamadoTable Data Gateway y Row Data Gateway
Nuestro Controlador IndexController quedaría de la siguiente forma:
quickstart/application/controllers/IndexController.php
-
<?php
-
require_once 'Zend/Controller/Action.php';
-
class IndexController extends Zend_Controller_Action
-
{
-
public function init()
-
{
-
$this->view->baseUrl = $this->_request->getBaseUrl();
-
}
-
public function indexAction()
-
{
-
require_once 'CommentsTable.php';
-
$form = CommentsTable::getAddCommentForm();
-
if ($this->getRequest()->isPost()) {
-
if ($form->isValid($_POST)) {
-
$values = $form->getValues();
-
}
-
}
-
$this->view->form = $form;
-
$this->view->title = 'Comentarios';
-
$this->view->comments = CommentsTable::getComments();
-
}
-
}
Finalmente la definición de nuestra vista actualizada sería:
quickstart\application\views\scripts\index\index.phtml
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-
<title>Zend Framework Quick Start</title>
-
</head>
-
<body>
-
<ul>
-
<?php foreach ($this->comments as $comment) :?>
-
<?php endforeach; ?>
-
</ul>
-
<?= $this->form; ?>
-
</body>
-
</html>
Hemos llegado al final de nuestro artículo, en el próximo y último capitulo de esta serie Comenzando con Zend Framework explicaremos como implementar un sistema de layout en nuestro sistema con Zend_Layout, no se lo pierdan y nos vemos próximamente.
Comentarios
29 Responses to “Comenzando con Zend Framework: IV Parte”
Deja tu comentario

Muy buen artículo, estimado!
Pregunta (desde el desconocimiento), ¿me puedes explicar por qué (conceptualmente) agregas el “getAddCommentForm” en el Modelo?
Muchas veces yo tampoco tengo muy claro donde poner dentro del MVC algunas funcionalidades (falta de experiencia), pero en este caso estaría el Modelo resolviendo la creación del Form, algo más de la capa de Presentación… a mi se me hubiera ocurrido hacerlo más en el Controller (pero no quiere decir que esté bien).
¿Me iluminas?
Enrique, en el Modelo deberían estar todas las clases relacionadas con los datos, teniendo en cuenta que Zend_Form hace manejo de estos almacenando los valores ingresados por el usuario para procesarlos, todo ese procesamiento llámese validación filtro etc., perfectamente podría ir en la capa de Modelo.
Estuve investigando bastante sobre la manera en que Magento Ecommerce implemento ZF en su sistema, ellos guardan todas las clases que se relacionan con los datos del sistema en el modelo (Mage_Core_Model), tales como las de configuraciones con simpleXML, Sesiones, Validaciones, cookie, Date, Base de datos, email etc.
También pasa por un tema de diseño de cada desarrollador, dejarlo en el controlador también es una correcta forma de hacerlo.
saludos,
Buena serie de artículos!
Estoy esperando como sigue…
Un saludo
Isidro
Luego seguiremos con Zend_Layout.
Estimado, también estuve viendo Magento (entre otros proyectos) y sus criterios no me terminaron de convencer.
Lamentablemente no he encontrado hasta el momento una guía conceptual clara sobre cómo estructurar un sistema usando -particularmente- un MVC, y -particularmente- con las posibilidades de Zend.
Acabo de encontrar un artículo donde hacen otra implementación: colocan el Form en un Helper.
“Teóricamente” me ajusta más que el Form quede resuelto en el ámbito de las vistas y no en el Modelo o en el Controler en sí.
Zend Form, donde generar el html
Estimado, esta buena la forma de implementarlo en las vistas como helper, tiene lógica.

Muy buen post, hacen falta bastante posts del ZF en español
Saludos
Hola, no logro hacerlo andar, me da el siguiente error:
“Fatal error: Uncaught exception ‘Zend_Db_Table_Exception’ with message ‘No adapter found for CommentsTable’ in C:\wamp\www\LibreriaV1\library\Zend\Db\Table\Abstract.php:548 Stack trace: #0 C:\wamp\www\LibreriaV1\library\Zend\Db\Table\Abstract.php(531): Zend_Db_Table_Abstract->_setupDatabaseAdapter() #1 C:\wamp\www\LibreriaV1\library\Zend\Db\Table\Abstract.php(268): Zend_Db_Table_Abstract->_setup() #2 C:\wamp\www\LibreriaV1\application\models\CommentsTable.php(26): Zend_Db_Table_Abstract->__construct() #3 C:\wamp\www\LibreriaV1\application\controllers\IndexController.php(22): CommentsTable::getComments() #4 C:\wamp\www\LibreriaV1\library\Zend\Controller\Action.php(502): IndexController->indexAction() #5 C:\wamp\www\LibreriaV1\library\Zend\Controller\Dispatcher\Standard.php(293): Zend_Controller_Action->dispatch(’indexAction’) #6 C:\wamp\www\LibreriaV1\library\Zend\Controller\Front.php(914): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #7 C:\wamp\ in C:\wamp\www\LibreriaV1\library\Zend\Db\Table\Abstract.php on line 548″
Que puede ser?
Te faltó lo más importante “ver bien las instrucciones y leer con cuidado”.
El error claramente dice que no encuentra el adaptador de base de datos en el objeto Table “específicamente en CommentsTable”
¿cómo lo hago?
fácil, en el bootstrap file:
$db = Zend_Db::factory($config->database);
Zend_Db_Table_Abstract::setDefaultAdapter($db);
excelente tutorial, ahora una duda, por que guardo en un .ini el user y password, este archivo puede ser editado desde afuera.. por que no se guarda en un php como siempre haciamos (?)
en un ambiente de producción el ini se debería de colocar fuera del root del web server o bien con restricciones .htaccess.
Además Zend_Config recibe la configuración como un array, por lo tanto es perfectamente posible incluir un archivo conf.php el cual declare el array con las configuraciones, en el manual se explica bien como.
saludos.
Muy buenas!!! a ver, he seguido el manual paso a paso, incluso al final he tenido que copiar literalmente el código del ejemplo. El caso es que no soy capaz de sacarlo del todo :S. No sé porqué pero no aparece el form al final, me muestra:
Comentarios
form; ?>
Creo que me falla aquí f ($form->isValid($_POST))
¿Teneis alguna idea de porqué?
gracias
perdón, el comentario era para la anterior entrada no para esta, jeje, la pondré allí también.
Has visto como nos volveríamos a leer? jeje.
Perdona mi ignorancia, pero estoy empezando con esto. ¿En qué directorio debe almacenarse la base de datos física?
Gracias de nuevo ;).
La base de datos, en general es un motor y funciona con un servicio. El directorio los configuras según el motor de bd
jauszkdl vyrtzcp uwbq uwtnelrfp edtshnm wdiyqot fqsvpwhtc
Nice site you have
Buenas tardes.
saludos.
estoy comenzando a trabajar con el Zend Frameworks.
y estoy probando el codigo de conexion a base de datos el aqui publicado y me arroja el siguiente error. Agradeceria cualquier ayuda al respecto. ya que las otras 3 partes de este blogs me funcionaron a la perfeccion.
disculpen el error es el siguiente:
Fatal error: Uncaught exception ‘Zend_Config_Exception’ with message ‘parse_ini_file(quickstart.ini) [function.parse-ini-file]: failed to open stream: No such file or directory’ in /var/www/ejemploZend2/library/Zend/Config/Ini.php:117 Stack trace: #0 /var/www/ejemploZend2/public/index.php(14): Zend_Config_Ini->__construct(’quickstart.ini’, ‘default’) #1 {main} thrown in /var/www/ejemploZend2/library/Zend/Config/Ini.php on line 117
Sie haben eine sch?ne Seite!
Me salio el mismo error que a larry.
Se debe modificar una linea del codigo de ejemplo:
en quickstart/public/index.php
linea 8 dice
$rootPath . ‘/application/config’ . PATH_SEPARATOR .
deberia decir:
$rootPath . ‘/application/configs’ . PATH_SEPARATOR .
(falto la “s” a “configs”)
Bueno, espero haber ayudado, mejor tarde quue nunca XD
excelente tutorial.. solo q la misma consulta en el tutorial de ZendFramework getting action (o como se escriba :$)… ponen los formularios dentro del model y cada una clase como UserForm.. etc etc ahi cada clase hace un extend a Zend_Form.. como hablando con otro amigo me cuenta q el html lo ingresa en los actions dentro de los controllers. Entonces.. mi duda mas q todo como me guio a estructurar una aplicacion… tanto en la parte de formularios, en la parte de acciones, en modulos de la aplicacion.. sinceramente tengo un mix de conceptos en mi cabeza q no me ayudan mucho… alguna sugerencia.. ??
Hola.
excelente tutorial, una duda que hay es la con la función $this->escape($comment->comments);
supongo que es para mostrar los datos del formulario, pero esta se declara en en algún lado??
Hola!! necesito q alguien m ayude, xq cuando yo estoy creando un proyecto nuevo y l cambio los nombres al controlador,modelo y vista m sale el sgte error:
The requested URL /pruebaAlbum/prueba was not found on this server.
es algo q no he podido entender xq en un ejemplo q tome d internet si m funciona, pero los nombres son index todos y al cambiarles el nombre no funciona..
Ya me di cuenta cual es el error…
Hola que tal? soy nueva en esto de zend y probando lo de los radio quisiera saber si hay alguna manera de saber de que al seleccionar una opcion del radio pueda aparecer cajas de texto y con la otra opcion aparecer otras cajas de texto.
y que despues obtener cual de los dos esta selecionado para saber en que tabla es que tengo que guardar.
El ejemplo que estoy usando es el registro de usuarios naturales y juridicos
Hola que tal!
Es que estoy intentando pasar valores que recibo en una vista a otra vista, las vistas son identicas en cuanto a los campos o tributos lo que cambia es que la primera tiene el boton que envia los valores a la otra vista.
Te muestro el codigo que tengo, y cuando hago el getValues no se trae los datos, carga el arreglo pero vacio.
en la primera vista el boton enviar tiene lo siguiente:
public function enviarAction()
{
$request = $this->getRequest();
$form = new Default_Form_Ejemplo();
if (!$form->isValid($request->getPost())) {
$variables = $form->getValues();
print_r($variables);
die();
}
$form = new Default_Form_Ejemplo2($variables);
$this->view->form = $form;
}
pero no hace nada en la segunta vista que es Ejemplo2 se quedan en blanco todas la cajas de texto.
Gracias espero puedan ayudarme…
Muy buen artículo, sigue así.