Calendário do advento Symfony dia 11: syndication feed
Anteriormente no symfony
A aplicação askeet está pronta para ser lançada em um (cedo) estágio beta. De faot, ela já poderia seduzir muito usuários, desde que as funcionalidades do centrais (fazer perguntas, ler respostas, contribuir com novas respostas) estão construídas. O problema é que usuários recorrentes acharão difícil manter-se atualizados com os últimos eventos do site do askeet. Você precisa provê-los com novas notícias, sem esforço, e há um jeito para isso: feed de notícias. Então, hoje, vamos adicionar um feed de notícias para o askeet.
Feed de Perguntas Populares
Link to the feed in the head
O que nós queremos é um RSS feed de perguntas populares inserido no <head> do layout global. O HTML resultante deveria parece como o a seguir:
[php]
<link rel="alternate" type="application/rss+xml" title="Popular questions on askeet" href="http://askeet/frontend_dev.php/feed/popular" />
Para fazer isso, abra o layout.php e adicione, no <head>:
[php]
<?php echo auto_discovery_link_tag('rss', 'feed/popular') ?>
Isso é tudo. O helper auto_discovery_link_tag (carregado automaticamente com a biblioteca de helpers AssetHelper.php ) transforma o module/action em um site URI, passando pelo motor de roteamento.
Instalando o plug-in
Symfony provê um plug-in sfFeed que automatiza a maior parte da geração de feed. Para instalá-lo, você irá usar a linha de comando.
$ symfony plugin-install http://plugins.symfony-project.com/sfFeedPlugin
$ symfony clear-cache
Isto instala as classes do plug-in no diretório askeet/lib/symfony/plugins/.
Se você quiser aprender mais sobre plug-ins, como eles extendem o framework e como você pode empacotar as funcionalidades que você usa, através de diversos projetos, em um plug-in, leia o capítulo sobre plug-ins do livro do symfony.
Não esqueça de limpar o cache desde que o diretório lib/ do projeto foi modificado, por causa do plug-in. De todo jeito, se você experimentar problemas com o comando plugin-install, talvez seja porque você não tem o PEAR instalado.
Nós falaremos sobre esta classe sfFeed posteriormente. Mas, primeiro, nós precisamos escrever algumas linhas de código.
Crie a ação (action)
O feed aponta para uma ação (action) popular da ação (action) feed. Para criá-lo, digite:
$ symfony init-module frontend feed
Então, edite o arquivo askeet/apps/frontend/modules/feed/actions/action.class.php e adicione, no método a seguir:
[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('rss201rev2');
// 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;
}
Defina o parâmetro customizado app_feed_max_question no seu arquivo de configuração askeet/apps/frontend/config/app.yml:
all:
feed:
max: 10
Mude a configuração do view
Por padrão, o resultado da nossa ação feed/popular será decorada pelo layout, e irá ter content-type text/html. Istoo não é o que a gente quer. Assim, crie um view.yml no diretório askeet/apps/frontend/modules/feed/config/ contendo:
all:
has_layout: off
template: feed
Isto desativa o decorador e força o output template para feedSuccess.php, seja qual for a ação.
Escreva o template
Isto é porque o template é muito simples e pode ser reutilizado para outros feeds. Apenas escreva este simples template askeet/apps/frontend/modules/feed/templates/feedSuccess.php:
[php]
<?php echo $feed->getFeed() ?>
Teste-o
Agora, limpe o cache (pois a configuração mudou), recarregue alguma página do site, e perceba o ícone do feed no seu browser favorito. verifique o feed requisitando-o manualmente:
http://askeet/feed/popular
O resultado é:
[xml]
<?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>
Tão rápido?
A mágica
Agora, você diria: como que o symfony sabe onde encontrar o autor da pergunta, o seu email, e como que o symfony adivinhou a URI dos detalhes da pergunta ? A resposta: É mágica!
Se você não acredita em mágica, então atravesse a cortina e conheça a classe sfFeed. Esta classe é capaz de interpretar os nomes dos métodos do objeto que é passado como parâmetro para os métodos ->setItems(). O objeto Question tem um método ->getUser(), assim, ele é usado para encontrar o autor da pergunta. O objeto User tem um método ->getEmail(), assim, este é, também, usado para determinar o email do autor da pergunta. E o nome da regra passada para o método ->setFeedItemsRouteName() é:
question:
url: /question/:stripped_title
param: { module: question, action: show }
Veja que há um parâmetro stripped_title. Assim, o método ->getStrippedTitle() do objeto Question é chamado para determinar o URI da pergunta.
Tudo isto acontece porque the getter method names fazem sentido - e a classe sfFeed entende objetos designados daquela forma. Os mecanismos de interferência desta classe são descritos, em detalhes, no capítulo de feeds do livro do symfony - refira-se a ele para ver como perguntar, por exemplo, um feed sem endereços de email, mesmo se o método ->getEmail() existe para o objeto do autor.
Nota: O view do feed tem um content-type XML, assim, o symfony será esperto o suficiente para não adicionar a barra de web debug a ele ( caso contrário, o XML não seria válido). Se, mesmo assim, você precisar desativar a barra de web debug manualmente, você pode sempre chamar:
sfConfig::set('sf_web_debug', false);(find more about the web debug toolbar in the debug chapter of the symfony book).
Melhorias na Interface
Roteamento
O URL de um feed é tão importante quanto este próprio, assim, adicione o seguinte ao final do arquivo routing.yml:
# feeds
feed_popular_questions:
url: /feed/popular
param: { module: feed, action: popular }
Imagem RSS
Sempre que um link para uma lista tiver um campo de correspondência, um ícone RSS legal é mostrado, jutamente com um link para o RSS. Como isto irá acontecer umas poucas vezes, crie a função link_to_feed() no arquivo GlobalHelper.php:
[php]
function link_to_feed($name, $uri)
{
return link_to(image_tag('feed.gif', array('alt' => $name, 'title' => $name, 'align' => 'absmiddle')), $uri);
}
Você encontrará a imagem feed.gif no repositório SVN.
Agora, edite o arquivo modules/sidebar/templates/defaultSuccess.php como a seguir:
[php]
<li><?php echo link_to('popular questions', '@popular_questions') ?> <?php echo link_to_feed('popular questions', '@feed_popular_questions') ?></li>
Vejo você amanhã
Este tutorial deveria durar uma hora, e somente quinze minutos passaram-se. Você está preocupado ? Não fique. Esta é mais uma das aulas de programação ágil: se você encontrar uma solução muito simples para um problema, é provável que seja o correto. Não é necessário passar muito tempo para desenvolver uma funcionalidade se esta já funciona. E você, agora, sabe que quinze minutos são necessários para configurar, testar e lançar um feed RSS. Após tudo, o symfony oferece ferramentas web profissionais para os mais preguiçosos, assim, curta seu tempo livro e esqueça seu computador por hoje.
Se você quiser fazer mais no symfony, tente fazer um fedd para as últimas perguntas, últimas respostas geral, e últimas respostas para uma pergunta em particular. Isto não deveria lhe custar mais que mais quinze minutos, assim, você terá tempo para fazer o download do código completo do repositório SVN do askeet, marcado release_day_11, e conferir se você fez corretamente. Cuidado que há uma dificuldade implícita - preste atenção na regra de roteamento usada para o feed dos últimos comentários.
E se você ainda tem alguns minutos sobrando, vá para o fórum do askeet e expresse-se.
Amanhã, nós enviaremos emails com o symfony, porque nós temos certeza que alguns dos nossos usuários esquecerão seus códigos de acesso. Até lá, durma bem.