レベル: 中級 Nicholas Chase (nicholas@nicholaschase.com), President, Chase and Chase, Inc.
2007年 4月 10日 フィードが、単に新しいコンテンツを誰かのブログに対してアナウンスする以上のものになり、構成されたデータが含められるようになるにつれ、配信可能なデータをすべてフィードに含めるのは避けたいという状況が起きてくるものです。このヒントは、ユーザーが「next」と「previous」というリンクあるいはボタンを使ってページを操作できるAtom フィードを作成する方法について説明します。このヒントでは PHP を使ってこの機能を実現しますが、他のプログラミング言語を使用する場合も考え方は同じです。
対象とするフィード
一例として、Syfy Portal のニュース・フィードを見てみましょう。このフィードは、3000 を超えるアーカイブされたニュースの話題を含んでいる可能性があります(「参考文献」にリンクがあります)。こうしたメッセージの多くは何年も前の古いものであるため、実際にこうしたすべてのメッセージをフィード・リーダーでダウンロードしたいと思う人は、まずいません。この問題を解決するために、Atomの仕様では、入手可能な情報の一部分のみを送信する必要性が考慮されています。
この場合の Atom の仕様では、アプリケーションを補助するための、いくつかのリンク要素を追加することを義務づけています。リスト 1 はその一例を示しています。
リスト 1. フィードのサンプル
<?xml version="1.0" encoding="us-ascii"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>SyFy Portal Headlines</title>
<link href="http://www.syfyportal.com"/>
<updated>2007-01-23T10:34:22Z</updated><id>http://www.syfyportal.com/a
tomfeed.php</id><subtitle>Your Premier Source For Science Fiction and
Fantasy News Since 1998</subtitle>
<link rel="alternate" type="text/html" hreflang="en"
href="http://www.syfyportal.com/"/>
<link rel="self" type="application/atom+xml"
href="http://www.syfyportal.com/atomFeed.php"/>
<link rel="first" href="http://www.syfyportal.com/atomFeed.php"/>
<link rel="next" href="http://www.syfyportal.com/atomFeed.php?page=2"/>
<link rel="last"
href="http://www.syfyportal.com/atomFeed.php?page=147"/>
<entry>
<id>http://www.syfyportal.com/news423172.html</id><title>'Heroes'
Holds Its Own Against '24'</title>
<link rel="alternate" type="text/html"
href="http://www.syfyportal.com/news423172.html"/>
<author><name>Michael
Hinman</name></author><updated>2007-01-23T10:03:08Z</updated>
<content>Who will win in the battle between NBC's "Heroes" and Fox's "24"? In
terms of overnight ratings, it's actually a virtual tie."Heroes" slid a bit in the
ratings to earn an 8.5 rating/12 share according ...</content>
</entry>
<entry>
...
|
この場合は最初のページを見ているので、このページは 4 つの情報を指定しています。第 1 の情報は、実際のページの URL です。第 2 の情報は一連のページのうちの最初のページのURL ですが、これは当然ながら現在の URL と同じです。
しかし、残りの 2 つの情報は多少の計算を行った結果として、それぞれ「next」ページと「last」ページを指定しています。このフィードには20 の項目が含まれているため、最初の 20 項目はこのページ上にあり、21 番目から 40 番目の項目はページ 2 に、と続きます。最初のページ以外のすべてのページには、さらに「previous」リンクがあります(リスト 2)。
リスト 2. ページ 2
...
<link rel="self" type="application/atom+xml"
href="http://www.syfyportal.com/atomFeed.php?page=2"/>
<link rel="first" href="http://www.syfyportal.com/atomFeed.php"/>
<link rel="previous"
href="http://www.syfyportal.com/atomFeed.php?page=1"/>
<link rel="next" href="http://www.syfyportal.com/atomFeed.php?page=3"/>
<link rel="last" href="http://www.syfyportal.com/atomFeed.php?page=147"/>
<entry>
...
|
この機能を PHP で作成するためには特別なスキルやモジュールは必要なく、単に系統だった方法が必要なだけです。
リンクを作成する
一例として、Syfy Portal のサイト用の Atom フィードを生成する PHP を考えてみてください。基本的なフィードの生成は単純です(リスト 3)。
リスト 3. 基本的なフィード
<?php
include("functions/engine.php");
header("Content-Type: text/xml");
$result = query("select * from content limit 20");
if (!result) {
echo "An error occured";
} else {
echo "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n\n";
echo "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n\n";
echo "<title>SyFy Portal Headlines</title>\n";
echo "<link href=\"http://www.syfyportal.com\"/>\n";
echo "<updated>".date('Y-m-d\TH:i:s\Z')."</updated>";
echo "<id>http://www.syfyportal.com/atomfeed.php</id>";
echo "<subtitle>Your Premier Source For Science Fiction and
Fantasy News Since 1998</subtitle>\n";
echo "<link rel=\"alternate\" type=\"text/html\"
hreflang=\"en\" href=\"http://www.syfyportal.com/\"/>\n";
echo "<link rel=\"self\" type=\"application/atom+xml\"
href=\"http://www.syfyportal.com/atomFeed.php\"/>\n";
for ($i=0; $i < count($result); $i++){
$author = query("select * from authors where ".
"id='".$result[$i]['authorid']."'");
$item = $result[$i];
echo "<entry>\n";
echo "<id>http://www.syfyportal.com/news42".
$item['id'].".html</id>";
echo "<title>".
stripslashes(htmlspecialchars($item['headline']))."</title>\n";
echo "<link rel=\"alternate\" type=\"text/html\" ".
"href=\"http://www.syfyportal.com/news42".$item['id'].".html\"/>\n";
$hometext = strip_tags($item['body']);
if (strlen($hometext)>101) {
$desctext = htmlspecialchars(substr($hometext, 0,
strpos($hometext, ' ', 200)))." ...";
} else {
$desctext = htmlspecialchars($hometext);
}
echo
"<author><name>".$author['name']."</name></author>";
echo "<updated>".date('Y-m-d\TH:i:s\Z',
$result[$i]['added'])."</updated>";
echo "<content>".stripslashes($desctext)."</content>\n";
echo "</entry>\n\n";
}
echo "</feed>";
}
?>
|
先頭から見ていくと、このサイトはいくつかの内部ルーチンを使っており、その中にはデータベース・トランザクションをラップするルーチンも含まれています。もちろん、これらのルーチンはこの記事で取り上げる話題ではありませんが、重要な部分は、query() 関数が行の配列を返し、その各行自体が配列として表現されているという点です。このページはこれらの項目のそれぞれをループし、Atom フィードを作成します。
ページング機能を追加するためには、まず入手可能なデータを分析することから始めます (リスト 4)。
リスト 4. ページング機能を追加する
<?php
include("functions/engine.php");
header("Content-Type: text/xml");
$result = query("select * from content");
if (!result) {
echo "An error occured";
} else {
$numberOfItems = count($result);
$numberOfPages = intval($numberOfItems / 20);
if (isset($_GET['page'])){
$thisPage = $_GET['page'];
} else {
$thisPage = 1;
}
$offset = ($thisPage - 1) * 20;
echo "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n\n";
echo "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n\n";
echo "<title>SyFy Portal Headlines</title>\n";
echo "<link href=\"http://www.syfyportal.com\"/>\n";
echo "<updated>".date('Y-m-d\TH:i:s\Z')."</updated>";
echo "<id>http://www.syfyportal.com/atomfeed.php</id>";
echo "<subtitle>Your Premier Source For Science Fiction and Fantasy News
Since 1998</subtitle>\n";
echo "<link rel=\"alternate\" type=\"text/html\".
" hreflang=\"en\" href=\"http://www.syfyportal.com/\"/>\n";
echo "<link rel=\"self\" type=\"application/atom+xml\".
" href=\"http://www.syfyportal.com/atomFeed.php\"/>\n";
echo "<link rel=\"first\".
" href=\"http://www.syfyportal.com/atomFeed.php\" />\n";
if ($thisPage > 1){
echo "<link rel=\"previous\" ".
"href=\"http://www.syfyportal.com/atomFeed.php?page=".($thisPage-1).
"\" />\n";
}
if ($thisPage < $numberOfPages){
echo "<link rel=\"next\" ".
"href=\"http://www.syfyportal.com/atomFeed.php?page=".($thisPage+1).
"\" />\n";
}
echo "<link rel=\"last\" ".
"href=\"http://www.syfyportal.com/atomFeed.php?page=".$numberOfPages.
"\" />\n";
for ($i=$offset; ($i < ($offset + 20) and $i < count($result));
$i++){
$author = query("select * from authors where
id='".$result[$i]['authorid']."'");
$item = $result[$i];
echo "<entry>\n";
...
|
これまでは、最大値の 20 を選択するための方法として、SQL 文でレコード数を制限していました。この場合は入手可能なデータをすべて選択するものとしています。その状態で、最大のページ数を決定します。
次に、現在どのページを表示すべきなのかを決定し、その情報を使ってオフセット、つまりスキップすべきレコードの数を決定します。
今度は実際のリンクを追加します。「first」リンク要素と「last」リンク要素はすべてのページに表示されますが、「previous」リンクは最初のページ以外、「next」リンクは最後のページ以外に表示されます。
最後に、適切なレコードのみを表示するように、つまり (何ページもある) 前のページのレコードをスキップした上で相変わらず 20 項目しか表示しないように、ループを調整します。(この場合、20はまったく任意の数字です。)
そうすると、見たいレコードのみをフィード・リーダーあるいは他のアプリケーションが要求できる Atom フィードができあがります。
まとめ
Atom 出版プロトコルは、必ずしも全データを要求者に送りたくないという事態を考慮しており、そうした機能を実現するための方法を提供しています。first、next、previous、lastといったリンク要素を使うことで、ユーザーは処理可能な大きさの塊の範囲でデータを操作できるようになります。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Atom paging samples | x-tipatom2-source.zip | 2KB | HTTP |
|---|
参考文献 学ぶために
製品や技術を入手するために
- RSS と Atom のための便利なユーティリティーとサンプルを集めたサーバー、Blogapps サーバーをダウンロードしてください。
議論するために
著者について  | 
|  | Nicholas Chase は、Lucent Technologies や Sun Microsystems、Oracle、the Tampa Bay Buccaneers などの会社で Web 開発に携わってきました。彼は高校の物理の先生であり、低レベル放射性廃棄物施設の管理者であり、オンライン SF 雑誌の編集者であり、マルチメディアのエンジニアであり、Oracle インストラクターであり、あるインタラクティブ・コミュニケーション会社の最高技術責任者でもあります。『XML Primer Plus』(Sams 刊) を含めて、何冊かの著作があります。 |
記事の評価
|