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 de sindicación de preguntas populares insertado en el <head>
del layout global. El HTML resultante debería quedar así:
<link rel="alternate" type="application/rss+xml" title="Popular questions on askeet" href="http://askeet/frontend_dev.php/feed/popular" />
Para hacer esto, abre el layout.php
y añade en el <head>
:
<?php echo auto_discovery_link_tag('rss', 'feed/popular') ?>
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 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:
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 echo $feed->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 version="1.0" encoding="UTF-8" ?> <rss version="2.0"> <channel> <title>Popular questions on askeet</title> <link>http://askeet/frontend_dev.php/</link> <description>A list of the most popular questions asked on the askeet site, rated by the community.</description> <language>en</language> <item> <title>What can I offer to my step mother?</title> <description>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.</description> <link>http://askeet/frontend_dev.php/question/what-can-i-offer-to-my-step-mother</link> <guid>11</guid> <pubDate>Sat, 10 Dec 2005 09:44:11 +0100</pubDate> </item> <item> <title>What shall I do tonight with my girlfriend?</title> <description>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.</description> <link>http://askeet/frontend_dev.php/question/what-shall-i-do-tonight-with-my-girlfriend</link> <guid>10</guid> <author>fp@example.com (Fabien Potencier)</author> <pubDate>Sat, 10 Dec 2005 09:44:11 +0100</pubDate> </item> <item> <title>How can I generate traffic to my blog?</title> <description>I have a very swell blog that talks about my class and mates and pets and favorite movies.</description> <link>http://askeet/frontend_dev.php/question/how-can-i-generate-traffic-to-my-blog</link> <guid>12</guid> <author>fz@example.com (François Zaninotto)</author> <pubDate>Sat, 10 Dec 2005 09:44:12 +0100</pubDate> </item> </channel> </rss>
¿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 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 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
:
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í:
<li><?php echo link_to('popular questions', '@popular_questions') ?> <?php echo link_to_rss('popular questions', '@feed_popular_questions') ?></li>
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, 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 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.
This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.