Caution: You are browsing the legacy symfony 1.x part of this website.

11日目: 配信フィード

1.0

復習

askeetアプリケーションは(初期の)ベータ版で立ち上げる準備ができています。当然のことですが、中核的な機能(質問をする、回答を読む、新しい回答を投稿する)が構築されているので、多くのユーザーを引き寄せるのかもしれません。 問題はユーザーが持続的にaskeetのWebサイト上の最新イベントを追跡するのが難しいと思うことです。労することなくユーザーに新鮮なニュースを提供する必要があります。そのためのメディア: ニュースフィードがあります。今日はaskeetにニュースフィードを追加しましょう。

人気のある質問フィード

ヘッドでフィードへのリンク

私たちが欲しいのは<head>のグローバルレイアウトに挿入された人気のある質問のRSSフィードです。HTMLの結果は次のようになります:

<link rel="alternate" type="application/rss+xml" title="Popular questions on askeet" href="http://askeet/frontend_dev.php/feed/popular" />

これを実現するには、layout.phpを開き、<head>に次のコードを追加します:

<?php echo auto_discovery_link_tag('rss', 'feed/popular') ?>

これですべてです。auto_discovery_link_tagヘルパー(オートロードされたAssetHelper.phpヘルパー)はmodule/actionをルーティングルールに渡してサイトのURIに変換します。

プラグインのインストール

symfonyはたいていのフィード生成を自動化するsfFeedプラグインを提供します。インストールするには、symfonyコマンドを使います。

$ symfony plugin-install http://plugins.symfony-project.com/sfFeedPlugin
$ symfony clear-cache

このコマンドはaskeet/lib/symfony/plugins/ディレクトリにプラグインのクラスをインストールします。

プラグインについて、どのようにフレームワークを拡張し、どのようにしてあなたがいくつかのプロジェクトを通して使うことが出来る機能をパッケージとして作成する、などのことをもう少し学びたいのでしたら、symfony bookのプラグインの章をご覧ください。

プロジェクトのlib/フォルダがプラグインのために変更されたので、キャッシュのクリアを忘れないでください。ところで、plugin-installコマンドで問題に遭遇していたら、それはおそらくPEARでインストールしていないからです。

sfFeedクラスについては後で話します。しかし、最初は数行のコードを書く必要があります。

アクションを作成する

フィードはfeedアクションのpopularアクションを指し示します。作成するには次のコマンドを入力します:

$ symfony init-module frontend feed

それからaskeet/apps/frontend/modules/feed/actions/action.class.phpを編集し、次のメソッドを追加します:

public function executePopular()
{
  // 質問
  $c = new Criteria();
  $c->addDescendingOrderByColumn(QuestionPeer::INTERESTED_USERS);
  $c->setLimit(sfConfig::get('app_feed_max'));
  $questions = QuestionPeer::doSelectJoinUser($c);
 
  $feed = sfFeed::newInstance('rss201rev2');
 
  // チャンネル
  $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.');
 
  // 項目
  $feed->setFeedItemsRouteName('@question');
  $feed->setItems($questions);
 
  $this->feed = $feed;
}

それからaskeet/apps/frontend/modules/feed/actions/action.class.phpを編集し、次のメソッドを追加します:

all:
  feed:
    max: 10

ビューの構成を変更する

デフォルトでは、feed/popularアクションの結果はレイアウトによってデコレートされ、text/html content-typeが含まれますが、私たちが欲しいものではありません。そこで、askeet/apps/frontend/modules/feed/config/ディレクトリでview.ymlを作成します:

all:
  has_layout: off
  template:   feed

これはデコレータの動作を停止し、アクションが何であれ、出力テンプレートをfeedSuccess.phpに強制します。

テンプレートを書く

テンプレートがとてもシンプルで他のフィードに再利用可能であるのはそういうわけです。このシンプルなaskeet/apps/frontend/modules/feed/templates/feedSuccess.phpテンプレートを書いてみてください:

<?php echo $feed->getFeed() ?>

テストする

キャッシュをクリアして(設定が変更されたからです)、サイトの任意のページもリフレッシュして、好きなWebブラウザのフィードアイコンに注目してください。手動でリクエストしてフィードを確認してください:

http://askeet/feed/popular

結果は次の通りです:

<?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>[email protected] (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>[email protected] (François Zaninotto)</author>
 
  <pubDate>Sat, 10 Dec 2005 09:44:12 +0100</pubDate>
</item>
  </channel>
</rss>

速いですか?

マジック

あなたはこう言うかもしれません: symfonyはどのようにして質問の著者、Eメールを見つけ、どのようにしてsymfonyは質問の詳細ページのURIを推測するのですかと?回答はこの通りです。マジックです。

マジックを信じないのでしたら、カーテンを越えて、sfFeedクラスに会ってください。このクラスは->setItems()メソッドにパラメータとして渡されたオブジェクトのメソッドの名前を理解します。QuestionオブジェクトはgetUser()メソッドを持ち、質問の著者を見つけるのに使われます。Userオブジェクトは->getEmail()メソッドは持っているので、これは著者のEメールを判断することにも使用されます。->setFeedItemsRouteName()メソッドに渡されるルール名は次の通りです:

question:
  url:   /question/:stripped_title
  param: { module: question, action: show }

このルールはstripped_titleパラメータを格納しているので、質問URIを判定するのにQuesitonオブジェクトの->getStrippedTitle()メソッドが呼び出されます。

ゲッターメソッドの名前には意味があるので、すべての作業が行われます - sfFeedクラスはそのように設計されたオブジェクトを理解するからです。このクラスの推測メカニズムがどのようにして求めるのか詳細はsymfony cookbookのフィードのチュートリアルで説明されています。たとえば、->getEmail()メソッドはオブジェクトのために存在しますが、Eメールアドレスを伴わないフィードです。

note

フィードのビューはXMLのContent-Typeを有するので、symfonyはこれにWebデバッグツールバーを追加しません(さもなければXMLは妥当ではなくなるでしょう)。Webデバッグツールバーを手動で無効にする必要がある場合、常に次のコードを呼び出すことができます:

   sfConfig::set('sf_web_debug', false);

(symfonyブックのデバッグの章でWebデバッグツールバーの多くの情報が見つかります)

インターフェイスの改善

ルーティング

フィードのURLはいつも重要です。routing.ymlに次のコードを追加します:

# フィード
feed_popular_questions:
  url:   /feed/popular
  param: { module: feed, action: popular }

RSSイメージ

リストのリンクに一致するフィールドがあるときは、RSSへのリンクと一緒にすばらしいRSSアイコンが表示されます。少しの時間しかかからないので、GlobalHelper.phplink_to_feed()関数を作成します:

function link_to_feed($name, $uri)
{
  return link_to(image_tag('feed.gif', array('alt' => $name, 'title' => $name, 'align' => 'absmiddle')), $uri);
}

SVNリポジトリでfeed.gifの画像が見つかります。

modules/sidebar/templates/defaultSuccess.phpを次のように編集します:

<li><?php echo link_to('popular questions', '@popular_questions') ?> <?php echo link_to_feed('popular questions', '@feed_popular_questions') ?></li>

それではまた明日

このチュートリアルは最後の一時間の予定で、15分しか過ぎていませんでした。困りませんでしたか?アジャイルプログラミングのレッスンの他のものです。 あなたの問題に対して、とてもシンプルなソリューションを見つけたら、おそらくはそれは正しいものです。すでに動作しているのであれば、機能を開発するのに多くの時間をかける必要はありません。今や、15分でセットアップしてテストとRSSフィードを立ち上げられることがわかっています。要するにsymfonyは無精な人のためのプロフェッショナルなWebツールを提供しますので、今日は自由な時間を楽しみ、コンピュータから離れましょう。

symfonyの素材が欲しいのでしたら、最新の質問、一般での最新の回答と、特別領域での質問への最新の回答などのために新しいフィードを作ってみてください。15分以上はかかりませんので、release_day_11とタグづけされたaskeet SVNリポジトリから全コードをダウンロードしてよくできたかチェックする時間があります。隠された困難は1つしかありません - 最新コメントのフィードのために使用されるルーティングルールに注意を払ってください。

まだ時間が残っているのでしたら、askeetのフォーラムに言って語ってください。

明日、symfonyでEメールを送ります。アクセスコードを忘れるユーザーがいるからです。それまではぐっすりお休みください。