Día once del calendario de symfony: sindicación feed
====================================================
Previamente en symfony
----------------------
La aplicación askeet está lista para ser lanzada en una (prematura) fase beta. De hecho, esto podría seducir a montones de usuarios desde que las características del núcleo (realizar preguntas, leer respuestas, contribuir con nuevas respuestas) son construidas. El problema es que los usuarios habituales encontrarán dificultades para mantenerse al día de los últimos eventos del sitio web askeet. Necesitas proporcionarles noticias frescas sin esfuerzo, y hay un medio para ello: sindicación de noticias. Así que añadamos hoy sindicación de noticias a askeet.
Sindicación de preguntas populares
----------------------------------
### Enlace a la sindicación en la cabecera
Lo que queremos es un [RSS][1] de sindicación de preguntas populares insertado en el `
` del layout global. El HTML resultante debería quedar así:
[php]
Para hacer esto, abre el `layout.php` y añade en el ``:
[php]
Eso es todo. El helper `auto_discovery_link_tag` (autocargado con la librería de helper `AssetHelper.php`) transforma el `module/action` en una URI de un sitio, pasando por el motor de enrutamiento.
### Instalar el plug-in
Symfony proporciona un plug-in `sfFeed` que automatiza la mayor parte de la generación de sindicaciones. Para instalarlo, usarás la línea de comandos de symfony.
$ symfony plugin-install local symfony/sfFeed
Esto instala las clases del plug-in en el directorio `askeet/lib/symfony/plugins/`, ya que la opción `local` le dice a symfony que instale el plug-in solo para la aplicación local. Lo podrías haber instalado para todos tus proyectos cambiando `local` por `global`.
Si quieres aprender más sobre plug-ins, sobre cómo extienden el framework y cómo puedes empaquetar las características que usas en varios proyectos en un plug-in, lee el [capítulo sobre plug-in](http://www.symfony-project.com/content/book/page/plugin.html) del libro de symfony.
No olvides limpiar la caché ya que la carpeta `lib/` del proyecto fue modificado a causa del plug-in. A propósito, si experimentas problemas con el comando `plugin-install` (lo cual probablemente pasará si no usas una versión de instalación de symfony vía PEAR), copia los archivos situados en el directorio `lib/plugins/symfony/plugins/sfFeed/` desde el repositorio SVN.
Hablaremos sobre esta clase `sfFeed` más tarde. Pero primero, necesitamos escribir unas pocas líneas de código.
### Crear la acción
La sindicación apunta a la acción `popular` del módulo `feed`. Para crearlo, escribe:
$ symfony init-module frontend feed
Luego edita `askeet/apps/frontend/modules/feed/actions/action.class.php` y añade el siguiente método:
[php]
public function executePopular()
{
// questions
$c = new Criteria();
$c->addDescendingOrderByColumn(QuestionPeer::INTERESTED_USERS);
$c->setLimit(sfConfig::get('app_feed_max'));
$questions = QuestionPeer::doSelectJoinUser($c);
$feed = sfFeed::newInstance('w');
// channel
$feed->setTitle('Popular questions on askeet');
$feed->setLink('@homepage');
$feed->setDescription('A list of the most popular questions asked on the askeet site, rated by the community.');
// items
$feed->setFeedItemsRouteName('@question');
$feed->setItems($questions);
$this->feed = $feed;
}
Define el parámetro personalizado `app_feed_max_question` en tu archivo de configuración `askeet/apps/frontend/config/app.yml`:
all:
feed:
max: 10
### Cambiar la configuración de la vista
Por defecto, el resultado de nuestra acción `feed/popular` será decorada por el layout, y tendrá un content-type `text/html`. Eso no es lo que queremos. Así que crea un `view.yml` en el directorio `askeet/apps/frontend/modules/feed/config/` con el contenido:
all:
has_layout: off
template: feed
Esto desactiva el decorador y fuerza que la plantilla de salida sea `feedSuccess.php`, sea cual sea la acción.
### Escribir la plantilla
Eso es porque la plantilla es muy simple y puede ser rehusada por otras sindicaciones. Tan solo escribe esta simple plantilla `askeet/apps/frontend/modules/feed/templates/feedSuccess.php`:
[php]
getFeed() ?>
### Testearlo
Ahora vacía la caché (ya que la configuración ha cambiado), actualiza cualquier página del sitio, y date cuenta del icono de sindicación de tu navegador web preferido. Comprueba la sindicación solicitando manualmente:
http://askeet/feed/popular
El resultado es:
[xml]
Popular questions on askeet
http://askeet/frontend_dev.php/
A list of the most popular questions asked on the askeet site, rated by the community.enWhat can I offer to my step mother?My stepmother has everything a stepmother is usually offered
(watch, vacuum cleaner, earrings, [del.icio.us](http://del.icio.us) account).
Her birthday comes next week, I am broke, and I know that
if I don't offer her something *sweet*, my girlfriend
won't look at me in the eyes for another month.
http://askeet/frontend_dev.php/question/what-can-i-offer-to-my-step-mother
11Sat, 10 Dec 2005 09:44:11 +0100What shall I do tonight with my girlfriend?We shall meet in front of the __Dunkin'Donuts__ before dinner,
and I haven't the slightest idea of what I can do with her.
She's not interested in _programming_, _space opera movies_ nor _insects_.
She's kinda cute, so I __really__ need to find something
that will keep her to my side for another evening.
http://askeet/frontend_dev.php/question/what-shall-i-do-tonight-with-my-girlfriend
10fp@example.com (Fabien Potencier)Sat, 10 Dec 2005 09:44:11 +0100How can I generate traffic to my blog?I have a very swell blog that talks
about my class and mates and pets and favorite movies.
http://askeet/frontend_dev.php/question/how-can-i-generate-traffic-to-my-blog
12fz@example.com (François Zaninotto)Sat, 10 Dec 2005 09:44:12 +0100
¿Es rápido?
La magia
--------
Ahora deberías decir: ¿cómo supo symfony dónde encontrar al autor de la pregunta, su e-mail, y cómo adivinó symfony la URI del detalle de una pregunta? La respuesta es: magia.
Si no crees en la magia, entonces vayamos tras la cortina y conozcamos la clase `sfFeed`. Esta clase puede interpretar los nombres de los métodos del objeto que es pasado como parámetro a sus métodos `->setItems()`. El objeto `Question` tiene un método `->getUser()`, así que es usado para encontrar al autor de una pregunta. El objeto `User` tiene un método `->getEmail()` , así que éste también es usado para determinar el e-mail del autor. Y el nombre de la regla pasado al método `->setFeedItemsRouteName()` es:
question:
url: /question/:stripped_title
param: { module: question, action: show }
Esto contiene un parámetro `stripped_title`, así que el método `->getStrippedTitle()` del objeto `Question` es llamado para determinar la URI de la pregunta.
Todo eso sucede porque los nombres del método getter tienen sentido - y la clase `sfFeed` entiende los objetos diseñados de esa forma. Los mecanismo de interferencia de esta clase son descritos en detalle en el [capítulo sobre sindicación](http://www.symfony-project.com/content/book/page/syndication.html) del libro de symfony - recurre a él para ver cómo solicitar, por ejemplo, una sindicación sin direcciones de e-mail incluso si un método `->getEmail()` existe para el autor del objeto.
>**Note**: La vista de la sindicación tiene un content-type XML, así que symfony será suficientemente inteligente para no añadir la barra de herramientas de depuración web a ella (de otro modo el XML no sería válido). Si alguna vez necesitas deshabilitar la barra de herramientas de depuración web manualmente, siempre puedes llamar a:
>
> sfConfig::set('sf_web_debug', false);
>
>(encuentra más sobre la barra de herramientas de depuración web en el [capítulo de depuración](http://www.symfony-project.com/content/book/page/debug.html) del libro de symfony).
Mejoras de la interfaz
----------------------
### Enrutamiento
La URL de una sindicación es tan importante como una normal, así que añade lo siguiente al `routing.yml`:
# feeds
feed_popular_questions:
url: /feed/popular
param: { module: feed, action: popular }
### Imagen RSS
Siempre que un enlace a una lista tenga un campo correspondiente, a bonito icono RSS es mostrado, junto con un link al RSS. Como esto sucederá unas cuantas veces, crea una función `link_to_feed()` en `GlobalHelper.php`:
[php]
function link_to_feed($name, $uri)
{
return link_to(image_tag('feed.gif', array('alt' => $name, 'title' => $name, 'align' => 'absmiddle')), $uri);
}
Encontrarás la imagen `feed.gif` en el repositorio SVN.
Ahora, edita `modules/sidebar/templates/defaultSuccess.php` así:
[php]
Nos vemos mañana
----------------
Este tutorial fue preparado para durar una hora, y solo han pasado 15 minutos. ¿Te has aburrido? No. Esa es otra lección de la programación ágil: si encuentras una solución muy simple a tu problema, es probablemente la correcta. No hay necesidad de pasar demasiado tiempo desarrollando una característica si ya funciona. Y ahora sabes que solo 15 minutos son necesarios para montar, testear y lanzar una sindicación RSS. Después de todo, symfony ofrece herramientas web profesionales para perezosos, así que disfruta de tu tiempo libre y deja el ordenador por hoy.
Si quieres más symfony, intenta hacer una nueva sindicación para las últimas preguntas, las últimas respuestas en general, y las últimas respuestas a una pregunta en concreto. Esto no debería llevarte más de otros 15 minutos, así que tendrás tiempo de descargar el código completo desde el [repositorio SVN de askeet](http://svn.askeet.com/tags/release_day_11/), etiquetado como `release_day_11`, y comprobar si lo has hecho bien. Cuidado porque hay una dificultad oculta - presta atención a la regla de enrutamiento usada para la sindicación de los últimos comentarios.
Y si aún tienes unos cuantos minutos más, ve al [foro de askeet](http://www.symfony-project.com/forum/index.php/f/8/) y exprésate.
Mañana, enviaremos e-mails con symfony, porque estamos seguros de que nuestros usuarios olvidarán sus claves de acceso. Hasta entonces, duerme profundamente.
[1]: http://blogs.law.harvard.edu/tech/rss "RSS 2.01 specifications"