domingo, 17 de febrero de 2008

Symfony vs Zend Framework. 2- Comencemos con Symfony

Artículos de la serie:
  1. Definición del problema
  2. Comencemos con Symfony
En el capitulo anterior planteamos una pequeña aplicación para comparar Symfony y Zend Framework. En este parte empezaremos con el primero de los citados no sin antes recordar que, aunque pueda parecerlo en ciertos momentos, esto no es un tutorial ya que no se citan todos y cada uno de los paso dados para llegar a la aplicación final.

Antes de nada... ¡a leer!

Partiendo de unos conocimientos nulos sobre Symfony, si rebuscamos un poco en su portal web, encontraremos una par de cosas interesantes para hacernos a la idea de cómo empezar a trabajar.

http://www.symfony-project.org/tutorial/1_0/my-first-project
http://www.symfony-project.org/book/1_0/

El primero de los enlaces es un tutorial rápido en el que curiosamente se desarrolla un ejemplo muy similar al nuestro. Es obvio que ha resultado bastante útil a la hora de hacer esta prueba. Las principales diferencias con nuestro caso son:
  • Nuestro requerimiento de utilizar una base de datos MySQL.
  • El diseño de nuestras tablas, que no aprovecha las ventajas de las nomenclaturas predefinidas para los ficheros YAML.
  • Nuestro diseño gráfico que aplicamos de una forma bastante realista (como si un equipo de diseño nos lo entregara maquetado)
El segundo enlace es un libro que podremos consultar en formato html, obtenerlo impreso o, incluso, en formato PDF traducido al español gracias a librosweb.es Si bien no es necesario leerlo por completo para realizar este ejemplo de aplicación, no vendrá mal darle un vistazo rápido y tenerlo a mano para consultar alguna duda.

Además de esto tendremos toda la documentación habitual sobre el API a la que podremos recurrir cuando lo necesitemos

Diseñando la BD

Recordamos el diseño comentado en el capítulo anterior según el cual un artículo podía tener muchos comentarios de lectores:



En Symfony tentemos que plasmar nuestros diseños en YAML, así que para el diagrama anterior el archivo schema.yml correspondiente sería:
propel:
blog_articulo:
_attributes: { phpName: Articulo }
idarticulo: { type: integer, required: true, primaryKey: true, autoIncrement: true }
titulo: varchar(255)
cuerpo: longvarchar
fecha_creacion: {timestamp}
blog_comentario:
_attributes: { phpName: Comentario }
idcomentario: { type: integer, required: true, primaryKey: true, autoIncrement: true }

idarticulo: { type: integer, foreignTable: blog_articulo, foreignReference: idarticulo, onDelete:cascade }
author: varchar(255)
email: varchar(255)
body: longvarchar
fecha_creacion: {timestamp}

Una vez más hay que recordar que había una forma más fácil de hacer esto y es realmente la recomendable, consiste en usar ciertos nombres de campos preestablecidos para claves primarias, claves externas y campos de fecha. La siguiente definición se correspondería con ello:

propel:
blog_articulo:
_attributes: { phpName: Articulo }
id:
titulo: varchar(255)
cuerpo: longvarchar
created_at:
blog_comentario:
_attributes: { phpName: Comentario }
id:
articulo_id:
author: varchar(255)
email: varchar(255)
body: longvarchar

created_at:

Después de ejecutar este paso es natural pensar que alguien que se adentre en este framework deberá familiarizarse con el lenguaje YAML y con Propel. Esto incrementa un poco la curva de aprendizaje. Como anécdota basta decir que el que escribe esto perdió bastante tiempo hasta conseguir hacer funcionar el fichero YAML mostrado anteriormente y todo por culpa de un salto de linea que pasaba inadvertido.

Cargando el resultado en mysql

Como ya tenemos nuestro fichero de descripción de la base de datos, continuaremos generando las clases de nuestro modelo, que quedará alojado en sf_sandbox/lib/model/ y nos permitirá actuar con la base de datos sin utilizar sentencias SQL.

php symfony propel-build-model

Si como es nuestro caso la aplicación parte desde cero y no tenemos la base de datos creada en nuestro servidor, nos vendrá bien utilizar el siguiente comando para generar el archivo de intrucciones SQL que podremos utilizar más tarde:

php symfony propel-build-sql

Gracias al archivo generado y disponible en la ruta data/sql/lib.model.schema.sql podremos importar el diseño de la base de datos a nuestro servidor MySQL. Para ello usaremos la linea de comandos, la opcion restaurar de MySQL Administrator, PHPMyAdmin, etc. Alternativamente podríamos utilizar la instruccion:

php symfony propel-insert-sql

Esta instrucción es útil si lo tenemos todo bien configurado con Symfony para que actúe sobre el serividor MySQL ya que por defecto generará una base de datos SQLite. De hecho en nuestro caso ha sido necesario modificar la configuración para poder trabajar con MySQL.

Un poco de magia

Los formularios de creación, modificación y eliminación de datos, suelen ser una tarea bastante tediosa y monótona. Por suerte Symfony nos puede librar casi por completo de ello, y decimos casí porque es cierto que siempre terminaremos retocando algo de los formularios. Esto lo conseguimos en nuestro caso haciendo lo siguiente:

php symfony propel-generate-crud frontend articulo Articulo
php symfony propel-generate-crud frontend comentario Comentario
php symfony clear-cache

Modulos y acciones

Llegados a este punto tenemos gran parte de la lógica interna de nuestra aplicación desarrollada. Gracias a los comandos que acabamos de ejecutar, dentro del directorio frontend/modules tendremos creados los módulos articulo y comentario. Cada uno de ellos contiene los directorios actions y templates. De momento nos ocuparemos del primero, donde encontraremos el fichero actions.class.php En este fichero se nos ha creado una clase que contiene todas las acciones del módulo y que por supuesto podremos modificar según nuestras necesidades.

Sin entrar mucho en detalle, en nuestro modulo articulos tendremos, en el fichero actions.class.php, la clase articuloActions que contendrá, entre otras, las siguientes funciones:
  • executeList: muestra el listado de artículos utilizando la plantilla listSuccess.php
  • executeShow: muestra un determinado artículo utilizando la plantilla showSuccess.php
  • etc.
Por poner un ejemplo nosotros hemos modificado executeList para que muestre los artículos por orden descendente de fecha:
public function executeList()
{

$this
->nombreModul=$this->getModuleNam();
$c=new Criteri();
$c->addDescendingOrderByColum(ArticuloPeer::FECHA_CREACION);
$thi->articulos = ArticuloPeer::doSelect($c
);
}

Adaptando nuestro diseño inicial

En la introducción a esta serie escogimos el diseño Pluralism. Es el momento de adaptarlo a nuestra aplicación, para ello tomaremos el archivo css (style.css) y lo copiaremos en la ruta /web/css. Para hacer que nuestra web lo lea añadiremos la siguiente linea al archivo layout.php que se encuentra en /apps/frontend/templates/

php echo stylesheet_tag('style') ;

Por supuesto insertaremos esta linea antes del fin de la etiqueta html head.

Después de esto remaquetamos nuestro layout.php copiando el código html proporiconado por Pluralism. Es decir que añadimos las capas wrapper y todo lo que necesitemos para obtener el resultado esperado. Mostraremos parte del código:
<body>
<div id="wrapper">
<div id="wrapper2">
<div id="header">
<div id="logo">
<h1&gt
<?php echo link_to('Janfri Bloggart', '@homepage')?></h1>
</div>
<div id="menu">
<ul>
<li&gt
<?php echo link_to('Crear entrada','articulo/create')?></li>
<li&gt
<?php echo link_to('Lists de articulos','articulo/list')?></li>
</ul>
</div>
</div>
<!-- end #header -->
<div id="page">
<div id="content">
<?php echo $sf_data->getRaw('sf_content')?>
</div>


Observese que introducimos un link a la home como título y que en la zona de menús dejamos dos links más.

Con la instrucción $sf_data->getRaw('sf_content') mostramos la información correspondiente a la acción invocada del módulo actual.

Para mostrar el listado de títulos de posts recientes nos hemos ayudado creando una plantilla auxiliar llamada _articulos_listado.php que hemos hubicado en modules/articulo/templates/ Este tipo de plantillas se incluyen mediante la instrucción inclde_partial:

include_partial('articulo/articulos_listado',array('articulos'=>$articulos
));

Por lo demás, el trabajo en la capa de presentación se basa en modificar las plantillas existentes, por ejemplo, a la hora de dar de alta un artículo hemos cambiado el "select" cargado con los artículos existentes por un input hidden con el valor del articulo a comentar. De otro modo: Simfony es listo pero no perfecto. Nos ha proporcionado un formulario de creación de comentarios en el que podríamos elegir el artículo a comentar mediante un "select" pero no era lo que queríamos. También hemos ampliado los textarea que nos ha creado para el cuerpo de los artículos y los comentarios, por citar otro ejemplo.











Conclusiones


Tras todo lo comentado anteriormente llegamos a la conclusión de que en eso más o menos consiste el trabajo básico. Debemos modificar las acciones y las plantillas hasta conseguir los resultados deseados. Todo ello después de haber hecho un buen diseño de tablas y haber ejecutado los comandos que nos preparan todos los archivos. Fácil y rapido una vez te acostumbras al árbol de archivos, configuraciones, etc. No se le puede pedir más.

Además es de agradecer que Symfony diferencia entre el entorno de desarrollo y el de producción, ofreciendo en el primero bastante información útil a través de un menú flotante en nuestra propia página web. Podermos inspeccionar el valor de variables, mensajes de log, consultas SQL realizadas (a través de Propel), etc.

El precio para disfrutar de todo esto es el aprendizaje, tal vez mayor que con otros competidores ya que además del API, tendremos que tener conocimientos sobre YAML y Propel.

En definitiva dan ganas de seguir poniendo a prueba a Symfony ya que es una forma diferente de trabajar con PHP pero es el momento de comenzar con Zend.
Publicar un comentario