Una reflexión sobre Symfony2 y sus componentes

Me ha alegrado leer la noticia que resume la reunión de ayer día 3 de Noviembre en symfony.es, proyecto que mantiene Javier Eguiluz, en la que dice que Fabien Potencier, autor y líder del proyecto Symfony, quiere dar prioridad a la documentación de los Componentes del framework.

Es una gran noticia que se considere documentar cada componente para final de año, y va muy en la línea de lo que comentaba Fabien en su blog sobre qué es Symfony2 y qué no.

Fabien quiere dar mucha importancia a los Componentes ya que es la única forma de que Symfony2 esté presente en el mayor número de proyectos posibles.

En mi opinión, y como ya he expresado en otras ocasiones, Symfony2 es un framework enorme, que intenta solucionar demasiada problemática, y en mi experiencia, cuanto más grande sea la aplicación y cuanta más problemática se intente cubrir, más complejo después será encontrar un posible fallo en entornos que no se hayan tenido en cuenta para la misma. En aplicaciones orientadas a internet, el entorno de sistemas puede que no sea el estándar LAMP, sobre todo si nos enfrentamos a webs de alto tráfico.

Otro problema, que para otros es una virtud, es que el framework intenta hacer configurable todo, con el objetivo de que los proyectos sean lo más automatizables, mantenibles y dotarles de una capacidad de reutilización en la que llegue a ser innecesario tocar una línea de código. Esto en teoría, suma más horas de desarrollo al principio y luego hace el mantenimiento más barato. Sin embargo, en proyectos que se orientan a internet, la teoría queda muchas veces en evidencia.

Hay que tener en cuenta que el mundo php5 no es como el mundo .net o java. Es complicado que desarrolladores web de php, aun con experiencia, se conviertan tan puristas de repente (más teniendo en cuenta los presupuestos tan ajustados económicamente y en tiempo que se barajan en proyectos web para internet) como para adoptar y entender todas las buenas prácticas que te obliga a usar Symfony2.

Para la mayoría de desarrolladores, el disponer de componentes, no les obliga a comprender el funcionamiento de todo el framework y pueden usarlos en desarrollos más simples o que ya tengan hechos.

De hecho, viendo estas direcciones en el proyecto Symfony2, en mi propio proyecto Leophard, un framework mvc ligero para php que por diversas razones de peso he tenido que retrasar su desarrollo, usaré algunos de estos componentes como el EventDispatcherUniversalClassLoader, el Routing, Pimple o el HttpFoundation, que son ligeros y resuelven problemática muy importante del proyecto.

La gente de Drupal está usando algunos de estos componentes también en la próxima versión de su cms.

Leophard, próximos pasos y dos dudas

A principios de verano os adelanté una primera aproximación sobre lo que iba a ser Leophard, un framework para el desarrollo web con php (sí, otro más).

Pensaba que podría tener una primera versión para Septiembre pero como todo lo que puede complicarse se complica, no voy a poder alcanzar esta meta.

En parte no voy a poder alcanzarla, además de por estar hasta arriba de trabajo (no he podido tomarme ni un fin de semana de vacaciones todavía), va a ser por una serie de cambios que voy a asumir en mi forma de trabajar en general a partir de ahora.

TDD

El cambio más importante que voy a adoptar es aplicar sin excusas TDD es decir, desarrollo guiado por tests. Y lo primero que he empezado a hacer es a escribir los test sin escribir todavía una sola línea de código.

Es cierto que tenía un prototipo funcional con un sistema de enrutamiento, de vistas y controladores muy básicos ya funcionando. Sin embargo, me he dado cuenta de que ningún desarrollo y en especial un desarrollo de este tipo, debe ejecutarse sin asegurarse la calidad que te permiten obtener los test unitarios, siempre que un proyecto se plantee de esta forma desde el principio.

En teoría esto debería hacerme ir más lento al principio, pero creo que merecerá la pena para obtener una arquitectura de calidad y evitar problemas en el futuro.

Ciclos cortos de desarrollo

Cuando me puse a desglosar la complejidad de un framework de este tipo, aun queriendo hacer algo simple y ligero, las posibilidades de complicarlo para intentar cubrir posibles necesidades son difíciles de ignorar.

Por suerte cada vez tengo más control sobre mí mismo acerca de evitar ser demasiado previsor para problemas que no tocan y el objetivo principal del proyecto, que es conseguir un framework ligero y ante todo simple, me ayuda en esta meta.

Dividiré el desarrollo en fases muy cortas para evitar caer en la resolución de problemas no críticos y tener cuanto antes una versión que se pueda usar aunque no cubra todos los problemas que puedan cubrir otros frameworks como Symfony o Kohana.

Propel

Desde un principio he descartado el desarrollo de un orm propio ligero, es una auténtica locura y casi prefiero hacer un gestor de conexiones para PDO que intentar hacer un orm para el mismo.

Propel desde la versión 1.3 tiene una capa orm sobre PDO que funciona muy bien y es bastante más ligera y rápida que Doctrine2. También prefiero Propel a Doctrine2 porque lo encuentro más simple y porque al menos yo, me siento más cómodo usándolo.

De Propel hay dos cosas que no me gustan: la dependencia de Phing (que tiene los días contados) y por tanto de Pear (que lo odio) junto a que los esquemas y configuraciones se escriben en xml. Para esto último me haré una implementación para que estos xml puedan generarse desde php de forma sencilla y menos tediosa.

No obstante dejaré la puerta abierta para otras opciones.

Dudas en formularios y en la vista

Sobre la vista

Tengo una duda en la vista y es que no se por qué modelo decantarme, si por el modelo de herencia de Symfony2 o por el tipo de implementación decorator que teníamos en Symfony1.x.

Por ejemplo, en Symfony 1 teníamos un layout donde cargábamos el contenido de cada controlador en una variable llamada $sf_content. En las platillas usábamos include_component o include_partial para dividir las partes de nuestra aplicación web en la capa de vista. Por defecto la plantilla asociada a un controlador era contenida en la variable $sf_content que se incrustaba en el layout que indicásemos o se devolvía si indicábamos que esa vista no tenía layout.

En Symfony2 vemos un modelo basado en la herencia de vistas, algo que podemos encontrar en otros framework como asp.net mvc. En cada vista se indica el parent, en el que se ha definido un esqueleto de bloques, y se escribe el código html que su parent debe insertar en cada bloque.

Yo prefiero la opción que teníamos en Symfony1.x, pero no las tengo todas conmigo si este es el mejor modelo.

La vista usará la última versión de Smarty, que actualmente es el motor de plantillas más extendido y que más desarrolladores php conocen.

Sobre los formularios

Este es un tema que tengo que analizar con calma pero tengo una cosa clara: quiero que sea simple crear y validar formularios.

En la creación y validación tengo que pensar muy bien cómo hacerlo para evitar que el programador tenga que escribir mucho código o al menos tanto como en Symfony1.4.

Quiero simplificar el proceso a la hora de recibir los datos, hacer el binding y comprobar si es válido.

En symfony deberíamos hacer lo siguiente en el controlador:

  • Comprobar el tipo de método http para procesar el formulario en caso de que sea POST (en el más del 90% de los casos)
  • Hacer un $form->bind($array); para obtener y filtrar los datos
  • Hacer un $form->isValid() para comprobar que el formulario es válido.

Yo prefiero tener algo así en un sólo paso:

  • $form->validate(Request $request, $method=”post”);

Otra opción es que los formularios se validen en el mismo request de la petición, de una forma similar a como se hace con el request validation de asp.net mvc 3.

Es decir, la validación se haría en el mismo request del action del fomulario y no habría que ejecutarla de forma explícita en el controlador.

Tengo que dar unas vueltas a todo esto, sobre todo a la hora de crear los widgets y validadores.

Este será el último post de este tipo sobre Leophard que haga en este blog, intentaré montar un sitio web en las próximas semanas dedicado al proyecto.

Error al validar inserción en formularios en asp.net mvc: A value is required

Esto sucede porque mvc espera todos los campos especificados para una tabla antes de insertar un registro, incluido el campo de identidad que suele ser autonumérico.

Podemos excluir uno o varios campos a la hora de insertar un nuevo registro, mediante un filtro en la declaración del método para la acción responsable de hacer el insert.


[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Insert([Bind(Exclude="Id")] Object object)
{

//lógica para el insert aquí

}

Symfony – Usar helpers fuera de la vista

Aunque los helpers de Symfony están pensados para ser usados en la vista, nos puede resultar útil e incluso imprescindible algunas veces usarlos fuera de la misma.

Symfony 1.2 nos permite hacerlo de la siguiente manera:


/*creamos un array con los nombres de los helpers

que necesitamos y de los que dependan*/

$hprs = array('Url', 'Tag', 'Asset');

//cargamos los helpers

sfProjectConfiguration::getActive()->loadHelpers($hprs);

//ya podemos usarlos sin problema

$url = url_for('modulo/acción?variable=valor');

Trabajar con symfony y sql server 2005

En la actual versión de symfony se usa Propel junto a Creole para crear un orm y una capa de abstracción entre la base de datos y el resto de nuestra aplicación.

Esto nos permite desarrollar aplicaciones independientes del motor de base de datos que usemos.

Php utiliza oficialmente la librería mssql para conectarse a una base de datos Sql Server y aunque existe una opción mejor por parte de Microsoft en fase CTP, Propel (y por lo tanto Symfony) la utilizan para conectarse a este tipo de motor.

Sin embargo, para conseguir conectarse y operar con éxito con Sql Server 2005 hay que hacer una serie de configuraciones en php/symfony y hacks en creole.
(Espero que no os siente esto como un cubata de Baileys con tonica : )

Vamos a verlo paso por paso:

1- Actualizar la librería ntwdblib.dll a la versión 2000.80.194.0.

2- Activar las extensiones php_mssql y php_xsl en el php.ini.

Adicionalmente debemos indicar los siguientes parámetros para php_mssql:

mssql.datetimeconvert = 0
mssql.textlimit = 2147483647
mssql.textsize = 2147483647

3- Crear nuestra base de datos en Sql Server y asignar el login y permisos adecuados al usuario que usemos para conectarnos.

4- Editar el archivo schema.yml con nuestro esquema de base de datos.

5- Configurar la conexión a la base de datos:

[ruta_completa]\symfony.bat configure:database
“mssql://usuario:password@equipo\instancia/nombre_baseDatos”

6- Construir el modelo orm de symfony:

[ruta_completa]\symfony.bat propel:build_model

7- Editar el fichero MSSQLConnection.php ubicado en \lib\plugins\sfPropelPlugin\lib\vendor\creole\drivers\mssql dentro del directorio de symfony.

En el caso de que no se especifique un puerto en el string de conexión a la base de datos, creole te inserta el valor de puerto predeterminado para sql server. Sin embargo, en Sql Server 2005 esto provoca un fallo impidiendo realizar una conexión exitosa a la base de datos.

Para evitar que creole nos meta el puerto si o si, debemos modificar la siguiente secuencia de control en MSSQLConnection.php:

if(!empty($dsninfo['port'])) {
$dbhost .= $portDelimiter.$dsninfo['port'];

}

//*else {
//$dbhost .= $portDelimiter.’1433′;
// }

Con estas modificaciones ya deberíamos poder trabajar con sql server 2005 desde symfony.

Instalar Symfony sobre IIS

Desde hace algún tiempo he estado leyendo sobre varios frameworks de desarrollo con php, que me permitiesen de una forma fiable automatizar trabajo que, a pesar de no tener una dificultad notable para alguien que sepa programar, te hace perder un montón de tiempo si quieres hacer las cosas bien.

La opción que más me ha gustado para php es sin duda Symfony y puesto que desarrollo tanto para plataformas UNIX/Linux como para sistemas Microsoft, me interesé por hacerlo funcionar e incluso utilizarla en proyectos que actualmente me encuentro desarrollando bajo sistemas Microsoft.

Voy a detallar como es una instalación de Symfony en IIS. Yo lo tengo funcionando sobre 2003 Server SP2 con IIS6

1 – Se descarga el código fuente de Symfony y se descomprime en un directorio en una de las unidades de disco duro del servidor. (Supongamos D:\symfony)

2 – Se crea un directorio cuyo contenido será el que usemos como sitio web. (Supongamos D:\dir_proyecto)

3 – Abrimos un terminal, nos situamos en “dir_proyecto” y ejecutamos lo siguiente para crear un proyecto:

D:\symfony\data\bin\symfony.bat init-project nuevo_proyecto

Ahora creamos una primera aplicación para ese proyecto:

D:\symfony\data\bin\symfony.bat init-app nueva_aplicacion

4 – Creamos un sitio web nuevo que apunte al directorio “D:\dir_proyecto\web”.

5 – Dentro del ese nuevo sitio web, creamos un directorio virtual que apunte a “D:\symfony\data\web\sf”

6 -  Si usamos isapi rewrite necesitamos ahora aplicar las reglas de redirecciones para nuestro sitio web. En la documentación oficial nos comentan una serie de reglas específicas para entornos de IIS. Esas reglas pueden darnos problemas a la hora de acceder a los archivos del directorio “D:\symfony\data\web\sf”.

Para evitar estos problemas, debemos ser fieles a las reglas definidas en el .htaccess que se ha creado en el directorio “D:\dir_proyecto\web” y añadir las reglas de seguridad relativas a entornos Microsoft.

Las reglas de redireccionamiento quedarían de la siguiente forma:
RewriteRule .*(?:global.asa|default\.ida|root\.exe|\.\.).* . [F,I,O]

RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f

RewriteRule (.*) /index.php [L]

Con esto ya deberíamos comprobar que todo funciona correctamente.

Nuevo blog en español sobre Cake PHP, de la mano de Hospedaxes

Cake PHP es uno de los mejores y más serios frameworks que podemos utilizar para desarrollar de una forma rápida y segura aplicaciones en php.

En Hospedaxes han creado un blog que podéis seguir en éste enlace, en el que nos publicar trucos y manuales basados en su experiencia profesional con éste excelente framework.

Blog Cake PHP

Un link sin duda para recomendar a todos los profesionales que desarrollen en php y quieran conocer éste framework para utilizar en algún proyecto.

Symfony vs Zend framework

A veces cuando desarrollamos en web para ciertos proyectos que requiren agilidad extrema de desarrollo o sea siempre, no tenemos la posibilidad de ponernos a desarrollar todo desde cero y nuestra opción más viable es optar por el uso de frameworks. En el caso de php tenemos varias opciones muy buenas como Zend Framework, Cake php o Symfony.

En sentido web veo un post que resume una comparativa entre la opción de Zend y Symfony, publicada en karlkatzke.com, que llega a la siguiente conclusión:

  • Comienzo: Symfony tiene mucha documentación y gente por detrás desarrollando y ayudando, algo de lo que anda un poco corto Zend.
  • Testing: Symfony viene con tareas de testing por línea de comandos y genera una clase vacía para ello al crear un controlador. Mientras que Zend no ofrece soporte para testing.
  • Plantillas: Zend tiene un sistema de plantillas un poco verde al que hay que hacerle algunos hacks para realizar algunas cosas. Symfony, al contrario, su sistema de plantillas es muy maduro, al cual le puedes añadir módulos.
  • Plugins: más de lo mismo, Symfony es extensible, Zend no.
  • Módulos de bases de datos: Zend usa ActiveRecord, mientras que en Simfony le puedes añadir el motor que desees, incluso Zend_Db.

Juction PHP, capa de persistencia de datos en php5

Juction es un framework para php que nos permite concentrarnos en nuestra lógica de aplicación, simplificando de una forma muy potente todo el trabajo con nuestra base de datos.

Juction mapea las consultas internas a la base de datos cuando trabajamos con objetos, olvidandonos de toda la carga CRUD (Create, Retrieve, Update y Delete).

Lo que sigue es un ejemplo de uso en Juction.

require("/Libs/Junction/Junction.php");
require("/Domain/JunctionUser.php");

//Aquí Juction mapea una típica clase de usuario

$junction = Junction::construct("JunctionUser");
//Ahora jugamos con la clase
$user = new JunctionUser();
$user->setEmail("foo@bar.com");
$user->setPassword("password");
$user->setDate(time());
//Esto insertará un nuevo usuario en la base de datos y devolverá un id, de forma transparente
$junction->save($user);
//un ejemplo con querys parametrizadas
$clause = $junction->createQuery("password = ?");
//Limpiamos el valor que pasamos como parámetro a la consulta
$clause->bind(0, "password");
//Recuperamos en un array de objetos mapeados para juction, el resultado de la query
$users = $junction->loadWhere($clause);

Están trabajando actualmente en el soporte para cosas más avanzadas como INNER JOINS, pero de momento éste proyecto le vendrá muy bien a más de uno.