ソーシャル・オブジェクトを Atom フォーマットで表現する

Activity Streams 標準の紹介

ソーシャル・ネットワーキング・サイトの人気は、人々がオンラインで何をしているかを表現する Web フィードのための新しい標準を生む結果となりました。Atom フォーマットの拡張である Activity Streams により、Web サイトがソーシャル・アクティビティーを配信できるようになります。この記事では Activity Streams フォーマットによるソーシャル・オブジェクトの表現方法を探り、アクティビティー・フィードのエンコーダーを PHP で作成する方法を学びます。そして、企業において役立つ可能性のある Activity Streams の用途について理解してください。

Ben Werdmuller, Consultant and writer, Freelance

Photo of Ben WerdmullerBen Werdmuller は、オープンソース・プラットフォームを専門とする Web ストラテジスト兼開発者です。Elgg の作成者の 1 人として、このソーシャル・ネットワーキング・フレームワークの技術リーダーを務めました。彼は http://benwerd.com/ に定期的にブログを投稿しています。



2010年 6月 15日

Web 上でのフィードは、マシンで読み取り可能なコンテンツの要約であり、通常は新しい順に並べられます。従来、大抵のフィードはよく使われている RSS または Atom という XML ベースのフォーマットでブログ・コンテンツを配信するために使われています。サイトによって公開されたコンテンツは、ユーザー・フレンドリーなアグリゲーターを使って購読することも、あるいはネットワークで接続されたソフトウェア製品で変換して解釈することもできます。

PHP の準備

この記事で紹介する PHP の例に従うには、PHP 5 以降が必要です。また、この言語を全面的に理解していることも前提条件となります。PHP のダウンロード・ページへのリンクは、「参考文献」に記載されています。

1999年以来、配信されたフィードはこのように使用されてきました。しかしここ数年の間、Web ユーザーは Facebook、MySpace、Twitter などといったサイトを通じ、より社交的な方法でコンテンツを使うようになってきています。これらのサイトが機能する仕組みは、人々が他のユーザーを「友達」に設定できるようにし、その友達のアクティビティーを、統合されたダッシュボードに集約するというものです。このようなサイトのユーザーは、1 つのコンテンツ・ストリームを購読するのではありません。興味の対象とするユーザーが作成、アップロード、共有しているすべてのコンテンツを見るために、個々のユーザーのコンテンツを購読します。

アクティビティー・ストリーム (Lifestream とも呼ばれます) とは、ある個人が特定のサイトで行ったすべてのアクティビティーを集めたものです。アクティビティー・ストリームを使用して、そこで収集された情報を利用しようとする Web ユーザーがますます増えていくなか、アクティビティー・ストリーム・データを配信して購読できるようにするのは当然の成り行きです。けれども RSS と Atom はソーシャル・メタデータをサポートしません。したがって、ソーシャル・アクティビティーを配信するには新しいフォーマットが必要となります。

よく使われる頭字語

  • RSS: Really Simple Syndication
  • URI: Uniform Resource Identifier
  • URL: Uniform Resource Locator
  • XML: Extensible Markup Language

そこで登場するのが、ソーシャル・オブジェクトを表現できるように Atom を拡張した新しい標準、Activity Streams です。まだ標準となってから日が浅いとは言え、Activity Streams は事実上 Web アプリケーション間でアクティビティーを配信するための標準的な手段に急速になりつつあります。例えば、MySpace、Facebook、TypePad ではいずれも、現在 Activity Streams 準拠の XML フィードを生成しています。けれどもこの技術はコンシューマーの Web 環境だけのものではありません。企業イントラネットや企業内部のソフトウェアがソーシャル化されているなか、ビジネス上の確固たる理由によって、機能としての Activity Streams の実装が後押しされます。この記事では Activity Streams について詳しく説明し、エンタープライズ環境に利用できる可能性を検討します。そして、PHP を使用して Activity Streams フィードを解釈する例を紹介します。

Activity Streams の起源

Activity Streams は、DiSo Project (「参考文献」を参照) から生まれました。DiSo Project は、WordPress ブロギング・プラットフォーム用に開発されたプラグインを使って分散ソーシャル・ウェブを構築することを目的としたオープンソースの取り組みです。DiSo モデルでは、各ユーザーのプロフィールは、それぞれ WordPress による個別のブログになっており、インターネットに接続された任意のインフラストラクチャー上にホストすることができます。そのため、ユーザーのアクティビティーは、WordPress サイト間でのソーシャル・アクションとしてインターネット上で発生します。

この手法で重要となる部分は、配信フォーマットです。1 つのサイトで何億人ものユーザーを収容する Facebook のようなサイトとは対照的に、DiSo は WordPress サイトごとに 1 人のユーザーしかいないことを前提とします。そのため、友達が何をしているのかを一目見るには、その友達のフィードを購読し、そのフィードを構文解析して内部データ構造にした後、集約されたインターフェースで表示するという方法しかありません。

XML は、この手法を実装する技術として申し分ありません。なぜなら、XML はプラットフォームに依存することなく、公開するにも構文解析するにも簡単で、専門的な技術は何も必要ないからです。DiSo Project はさらに一歩先を行き、Atom フィード・フォーマットの拡張として Activity Streams 標準を考え出しました。

RSS の代替手段として考案された Atom には、以下の特徴があります。

  • 100 パーセント、ベンダーに依存しない
  • 誰でも実装できる
  • 誰でも自由に拡張できる
  • 簡潔かつ詳細な仕様である

ベンダーに依存しないこと、拡張性があること、そして簡潔な仕様であることはすべて、将来も使い続けられる標準には不可欠な要素です。Activity Streams 標準を分散ソーシャル Web の有望な基軸にするためには、やはりこの 3 つの原則に従う必要がありました。さらに Atom の拡張性のおかげで、Activity Streams は既存のアプリケーション・ロジックと既存のパーサーを活用することができます。Atom の処理を行うコードがすでにあるのであれば (または、多くの既存のライブラリーのいずれかを使用すれば)、理論上、追加で開発しなければならないコードはほんのわずかです。

2009年 3月、MySpace は初の、Activity Streams フォーマットでフィードを公開する大手のソーシャル・メディア・プロバイダーとなりました。それ以来、Facebook、Hulu、TypePad、Opera などの他の多くのプロバイダーが MySpace に倣っています。けれども Activity Streams の適用範囲は Facebook などのサイトに限られてはいません。例えばイントラネットは、企業内、あるいは企業間でのソーシャル・アクティビティーの情報によって大幅に改善することが可能です。Activity Streams フォーマットは、企業で行われているさまざまなやりとりを追跡し、目標に向けた進捗具合を定量化するために、さまざまな商用ソーシャル・メディア・サイトでの複数のストリームを集約するという可能性も創出します。管理、分析、アルゴリズム、あるいはユーザーのいずれの観点から見ても、社会的慣習を追跡できるということは、新たな種類のソフトウェア・アプリケーションを生みだす数多くの機会をもたらします。


アクティビティー・ストリームについての詳細

Activity Streams は Atom を拡張し、http://activitystrea.ms/spec/1.0/ XML 名前空間をベースとした新しいスキーマ要素をいくつか追加しています。

Atom フィードを構成する主要な要素は、初期メタデータ (例えば、フィードのタイトル、作成者、フィードの URL、フィードが参照するコンテンツ全体の URL など) が含まれる 1 つの feed 要素です。この要素の中には任意の数の entry 要素があり、これらの要素によってフィードに含まれるコンテンツの項目が定義されます。リスト 1 に一例として、私の Web サイトによる Atom フィードを記載します。この Atom フィードには entry 要素が 1 つしかありません。

リスト 1. 著者の Web サイトによる Atom フィードの例
<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
  xml:base="http://benwerd.com/wp-atom.php"
   >
    <title type="text">Ben Werdmuller von Elgg</title>
    <subtitle type="text"></subtitle>

    <updated>2010-05-01T13:13:04Z</updated>

    <link rel="alternate" type="text/html" href="http://benwerd.com" />
    <id>http://benwerd.com/feed/atom/</id>
    <link rel="self" type="application/atom+xml" href="http://benwerd.com
/feed/atom/" />

    <entry>
        <author>
            <name>Ben Werdmuller von Elgg</name>
            <uri>http://benwerd.com/</uri>
        </author>
        <title type="html"><![CDATA[Sample article title]]></title>
        <link rel="alternate" type="text/html" href="http://benwerd.com/2010/05
/sample-article-title/" />
        <id>http://benwerd.com/2010/05/sample-article-title/</id>
        <published>2010-05-01T13:06:22Z</published>
        <content type="html" >
            ...
        </content>
    </entry>

</feed>

Activity Streams は、ソーシャル・オブジェクトに関するデータを各 entry 要素に挿入することによって Atom モデルを拡張します。これによって、entry 要素の子要素に組み込むことのできる内容が影響されることはありません。例えば、子要素である title および content にアクションのタイトルと人間が読み取れる説明を組み込むことも、標準 Atom フォーマットの content 要素にソーシャル・メタデータを組み込むこともできます。

Activity Streams の entry 要素には常に、以下を指定する 3 つの主要な要素が含まれます。

  • アクター (actor): アクションを実行している個人 (例: John Doe)
  • 動詞 (verb): 実行されているアクションのタイプ (例: added)
  • オブジェクト (object): アクションの実行対象の項目 (例: Ben's photo)

場合によっては、entry 要素にターゲット (target) を含めることもできます。ターゲットとは、アクションが実行または配置されたコンテナー・オブジェクトのことです (例: 「John Doe added Ben's photo to John's photo gallery」というアクションの場合、「John's photo gallery」の部分)。

entry 要素の中では、動詞、オブジェクト、アクター、およびターゲットを定義するために以下の要素が使用されます。

  • activity:verb 要素には、使用する動詞を定義する Atom URI が含まれます。
  • activity:object 要素には、任意の数の activity:object-type 要素 (次のパラグラフで説明) と、アクションのオブジェクトを記述するために必要なその他の要素が含まれます。
  • アクターは、既存の atom:author 要素によって定義されます (リスト 1 を参照)。
  • activity:target 要素は activity:object 要素と同様ですが、ターゲットを具体的に定義します (ターゲットが存在する場合)。

activity:objectactivity:targetatom:author の各要素の中には、1 つ以上の activity:object-type 要素があり、この要素の中に入れられた Atom URI が親オブジェクトを定義します。

動詞およびオブジェクトのタイプごとに、要素が保持できるプロパティーを定義する Atom URI があります。例として、リスト 2 に基本となる Activity Streams 仕様から抜粋した Atom URI を記載します。これらの Atom URI は、個人、共有する場合の動詞、ブログ投稿をそれぞれ定義しています。

リスト 2. 人、共有、ブログ投稿の基本 Activity Streams URI
http://activitystrea.ms/schema/1.0/person
http://activitystrea.ms/schema/1.0/share
http://activitystrea.ms/schema/1.0/article

上記の URI は、Activity Streams 仕様での人間が読み取れるエントリーに相当します。

リスト 3 では、リスト 1 の Atom フィードの例に示されている entry 要素を、Ben Werdmuller が投稿したブログ・エントリーを表す Activity Streams 表現に変換しました。

リスト 3. Activity Streams フォーマットでのリスト 1 のソーシャル・バージョン
<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xmlns:activity="http://activitystrea.ms/spec/1.0/"
  xml:lang="en"
  xml:base="http://benwerd.com/wp-atom.php"
   >
    <title type="text">Ben Werdmuller von Elgg</title>
    <subtitle type="text"></subtitle>

    <updated>2010-05-01T13:13:04Z</updated>

    <link rel="alternate" type="text/html" href="http://benwerd.com" />
    <id>http://benwerd.com/feed/atom/</id>
    <link rel="self" type="application/atom+xml" href="http://benwerd.com
/feed/atom/" />

    <entry>
        <id>http://benwerd.com/2010/05/sample-article-title/#actionID</id>
            <title type="text">Ben posted a blog entry.</title>
            <published>2010-05-01T13:06:22Z</published>
        <author>
            <name>Ben Werdmuller von Elgg</name>
            <uri>http://benwerd.com/</uri>
            <activity:object-type>
                http://activitystrea.ms/schema/1.0/person
            </activity:object-type>
        </author>
        <activity:verb>
            http://activitystrea.ms/schema/1.0/post
        </activity:verb>
        <activity:object>
            <title type="html"><![CDATA[Sample article title]]>
</title>
            <link rel="alternate" type="text/html"
 href="http://benwerd.com/2010/05/sample-article-title/" />
            <id>http://benwerd.com/2010/05/sample-article-title/</id>
            <published>2010-05-01T13:06:22Z</published>
            <content type="html" >
                ...
            </content>
            <activity:object-type>
                http://activitystrea.ms/schema/1.0/article
            </activity:object-type>
        </activity>
    </entry>
</feed>

以下の点に注意してください。

  • Activity Streams の語彙を定義するために、フィードの先頭に xmlns:activity=http://activitystrea.ms/spec/1.0/ 名前空間の宣言が追加されています。
  • Atom の entry 要素全体の id と、この要素に含まれる activity:object 要素の id を同じにすることはできません。
  • ブログ投稿に関する詳細 (リスト 1 に記載した標準 entry 要素に含まれる詳細) は、必要な activity:object-type 要素と併せて activity:object 要素に含まれています。
  • 標準の atom:title および atom:content 要素は、Activity Streams フィードをサポートしないパーサーで使用できるよう、そのまま残されています。

このアクションには 1 つのオブジェクトしかありませんが、Activity Streams のエントリーに複数のオブジェクトを組み込むこともできます。例えば、リスト 3 を修正して「Ben posted two blog entries」アクションを表現するなどです。意味的に多少異なる「Ben added two entries to his blog」というアクションを表現するには、ブログ全体を 1 つの activity:target 要素として追加します。

リスト 3 に記載したフィードの例では、意図的に基本的なコンテンツ・タイプを使用しましたが、Activity Streams 仕様では動詞とオブジェクトを特殊化することができます。例えば、共同プロジェクトを管理するアプリケーションでは、それぞれのユーザーがその担当の作業をいつ完了するかを示すことがあります。この場合、ソフトウェアが完了 (complete) に特化した動詞、そして作業 (task) に特化したオブジェクトを定義し、それぞれに固有のカスタム Atom URI を指定することになります。けれども多くの Activity Streams 対応のツールには、これらの特化された用語の知識がないため、アグリゲーションの際に問題が発生する可能性があります。この問題が発生する可能性を減らすため、Activity Streams フィードのエントリーには同じアクティビティーを記述する複数の動詞を組み込めるようになっています。その場合には、特定の動詞またはオブジェクトの上位要素一式をまるごと組み込むのが賢明です。単純に complete を基本動詞 update を特化させた動詞に、task を基本オブジェクト note を特化させたオブジェクトにすると、Activity Streams のエントリーはリスト 4 のようになります。

リスト 4. Activity Streams フィードに完了した作業が含まれる場合
<entry>
    <id>http://samplecompany.com/tasks/activity/23432/3242345/</id>
    <title type="text">Roger Taylor completed a task.</title>
    <published>2010-05-01T13:06:22Z</published>
    <author>
        <name>Roger Taylor</name>
        <uri>http://samplecompany.com/people/Roger+Taylor/</uri>
        <activity:object-type>
            http://activitystrea.ms/schema/1.0/person
        </activity:object-type>
    </author>
    <activity:verb>
        http://samplecompany.com/activity/schema/1.0/complete
    </activity:verb>
    <activity:verb>
        http://activitystrea.ms/schema/1.0/update
    </activity:verb>
    <activity:object>
        <title type="html"><![CDATA[Sample task]]></title>
        <link rel="alternate" type="text/html" href="http://samplecompany.com
/tasks/23432/" />
        <id>http://samplecompany.com/tasks/23432/</id>
        <published>2010-05-01T13:06:22Z</published>
        <content type="html" >
            ...
        </content>
        <activity:object-type>
            http://samplecompany.com/activity/schema/1.0/task
        </activity:object-type>
        <activity:object-type>
            http://activitystrea.ms/schema/1.0/note
        </activity:object-type>
    </activity>
</entry>

上記のリストでは、以下の点に注意してください。

  • オブジェクト・タイプの URI ごとに固有の activity:object-type 要素があります。
  • 動詞の URI ごとに固有の activity:verb 要素があります。
  • 特化されたオブジェクトと動詞のタイプには、それぞれに特化された固有の URI がなければなりません。

この記事を執筆している時点で、Activity Streams ウィキの資料には 21 の動詞と 25 のオブジェクト・タイプが記載されています。そのうち、公式の仕様文書で定義されている基本動詞は 11、基本オブジェクト・タイプは 19 です。Activity Streams パーサーは基本動詞および基本オブジェクトのそれぞれを認識して、適切に処理します。


Activity Streams エンコーダーの作成

Activity Streams 標準は単純なので、エンコーダーを作成するのは簡単です。この記事では、(例えば、PHP の echo 文を使用して) ストリングに変換したときの Activity Streams フィードを表す基本的な PHP エンコーダー・オブジェクトを作成します 完全なソース・コードを入手するには、「ダウンロード」を参照してください。

まず初めに、ActivityStreamEncoder というスタブ・クラスを作成し、このクラスに、エントリーの id、タイトル、説明を引数に取るコンストラクター・メソッドを定義します。また、Activity Streams エントリーを保持する専用配列、$entries も定義します。リスト 5 に、このクラスとコンストラクターを記載します。

リスト 5. コンストラクターが定義された基本 ActivityStreamEncoder クラス
class ActivityStreamsEncoder {

    private $id = "";
    private $title = "";
    private $link = "";
    private $entries = array();
    
    function __construct($id, $title = '', $description = '') {
        $this->id = $id;
        $this->title = $title;
        $this->description = $description;
    }    
}

次に、エントリー、オブジェクト、作成者それぞれの基本クラスを追加します。動詞は URI で構成されているだけなので、全体を通してこれらの URI をストリングとして参照します。エントリーとオブジェクトの公開日は、デフォルトで現在の日付に設定されるようにします (PHP の time() 関数を使用)。リスト 6 に、エントリーの基本クラスを記載します。

リスト 6. 基本 ActivityStreamEntry クラス
class ActivityStreamsEntry {
    
    public $id = "";
    public $title = "";
    public $author;
    public $objects = array();
    public $verbs = array();
    public $published;
    
    function __construct() {
        $this->published = time();
    }
    
    function addObject(ActivityStreamsObject $object) {
        $this->objects[] = $object;
    }
    function addVerb(string $verb) {
        $this->verbs[] = $verb;
    }
    function setAuthor(ActivityStreamsAuthor $author) {
        $this->author = $author;
    }
    
}

ActivityStreamsEntry クラスには、エントリーに作成者、オブジェクト、そして動詞を追加する単純なヘルパー・メソッドも組み込み、作成者、オブジェクト、動詞を適切な可変型の値にしています。

activity:object 要素の子要素は可変であるため、ActivityStreamsObject (オブジェクト・クラス) のプロパティーを取得するにはカスタム getProperty() メソッド、設定するにはカスタム setProperty() メソッドを使用します。これらのメソッドを定義しているのがリスト 7 です。このリストには ActivityStreamsObject と、ActivityStreamsObject の子クラスである作成者のクラスが記載されています。

リスト 7. Activity Streams オブジェクトと作成者のエンコーダー・クラス
class ActivityStreamsObject {
    public $properties = array();
    
    function getProperty($property_name) {
        if (isset($this->properties[$property_name])) 
return $this->properties[$property_name];
    }
    function setProperty($property_name, $property_value) {
        $this->properties[$property_name] = $property_value;
    }
    function __construct() {
        $this->published = time();
    }

    function addObjectType($object_type) {
        if (!isset($this->properties['object-type'])) $this->properties
                 ['object-type'] = array();
        $this->properties['object-type'][] = (string) $object_type;
    }
    
    function __toString() {
        $string = '';
        $string .= "\n<activity:object>";
        foreach($this->properties as $property => $value) {
            if (!is_array($value)) $value = array($value);
            switch($property) {
                case 'title':
                            $attr = 'type="html"';
                            break;
                case 'link':
                            $attr = 'rel="alternate" type="text/html" 
href="'.$value[0].'"';
                            $value = array(''); 
                            break;
                default:    $attr = '';
                            break;
            }
            if (sizeof($value))
                foreach($value as $val) {
                    if (empty($val))
                        $string .=  "\n\t<{$property} {$attr} />";
                    else if ($property == 'content' || $property == 'title')
                        $string .= "\n\t<{$property}
 {$attr}><![CDATA[{$val}]]></{$property}>";
                    else
                        $string .=  "\n\t<{$property} {$attr}>
{$val}</{$property}>";
                }
        }
        $string .=  "\n</activity:object>";
        
        return $string;
    }
    
}

class ActivityStreamsAuthor extends ActivityStreamsObject {
    function __construct() {
        $this->addObjectType("http://activitystrea.ms/schema/1.0/person");
    }
    function __toString() {
        $string = parent::__toString();
        $string = str_replace('activity:object>','author>',$string);
        return $string;
    }
}

上記の 2 つのクラスはそれぞれ、activity:object 要素、atom:author 要素の構造化バージョンを表します。これらのクラスを (例えばブラウザーにエコー出力して) ストリングに変換すると、構造化 XML が自動的に返されます。Activity Streams 要素ごとに相当する PHP クラスが独自の XML 表現を担当することで、簡潔な Activity Streams ハンドラー・オブジェクト一式を作成することができます。

リスト 8 では上記と同じようなクラスを追加して、今度は entry 要素全体を表します。

リスト 8. Activity Streams の entry 要素を表す PHP クラス
class ActivityStreamsEntry {

    public $id = "";
    public $title = "";
    public $author;
    public $objects = array();
    public $verbs = array();
    public $published;
    
    function __construct() {
        $this->published = time();
    }
    
    function addObject(ActivityStreamsObject $object) {
        $this->objects[] = $object;
    }
    function addVerb($verb) {
        $this->verbs[] = $verb;
    }
    function setAuthor(ActivityStreamsAuthor $author) {
        $this->author = $author;
    }

    function __toString() {
        
        $string = '';
        $string .=  "\n<entry>";
        $published = date('c',$this->published);
        $string .=  <<< END
        <id>{$this->id}</id>
        <title type="text"><![CDATA[{$this->title}]]></title>

        <published>{$published}</published>
END;
        if ($this->author instanceof ActivityStreamsAuthor) $string .=  
$this->author;
        if (sizeof($this->verbs)) foreach($this->verbs as $verb)
            $string .=  "\n<activity:verb>{$verb}</activity:verb>";
        if (sizeof($this->objects)) foreach($this->objects as $object)
            if ($object instanceof ActivityStreamsObject) $string .=  $object;
        $string .=  "\n</entry>";
        return $string;    
    }
}

entry 要素に含まれる Activity Streams の activity:verbactivity:objectatom:author の各要素を処理するために、リスト 8 のコードにも addVerb()addObject()、および setAuthor() メソッドが組み込まれています。

これで、ActivityStreamsEncoder クラス全体を変更して、対応する addEntry() メソッド (リスト 8ActivityStreamsEntry オブジェクトをストリームに追加するためのメソッド) と、Activity Streams フィード全体をエコー出力する __toString() マジック・メソッドを含めることができます。__toString() メソッドには、Activity Streams の語彙を正しく使用するために必要な XMLヘッダーと名前空間の宣言を組み込みます。リスト 9 に、addEntry() メソッドと __toString() メソッドを記載します。

リスト 9. リスト 5 の ActivityStreamsEncoder クラスに含める addEntry() および __toString() メソッド
function addEntry(ActivityStreamsEntry $entry) {
        $this->entries[] = $entry;
    }
    
    function __toString() {
        // Display header
        $string = '';
        $updated_time = date('c',time());
        $string .=  <<<END
<?xml version="1.0" encoding="UTF-8"?>
<feed
xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:activity="http://activitystrea.ms/spec/1.0/"
xml:lang="en"
>

<title type="text">{$this->title}</title>
<updated>{$updated_time}</updated>

<link rel="alternate" type="text/html" href="{$this->link}" />
<id>{$this->id}</id>
<link rel="self" type="application/atom+xml" href="{$this->id}" />

END;
        if (sizeof($this->entries))
            foreach($this->entries as $entry)
                if ($entry instanceof ActivityStreamsEntry) $string .= (string) $entry;
                
        $string .=  <<<END
</feed>
END;
        return $string;
    }

これで終わりです!ここで、すべてをまとめて構造化 Activity Streamsフィードにするには、一連のオブジェクトを結び付けてブラウザーにエコー出力します (リスト 10 を参照)。

リスト 10. リスト 5 から 9 に記載した PHP コードによる、リスト 4 の Activity Streams フィードのレダリング
// Create a new Activity Stream
$stream = new ActivityStreamsEncoder('http://samplecompany.com/tasks/activity/', 
     'Task activities at Sample Company');

// Define the action's object
$object = new ActivityStreamsObject();
$object->setProperty('id','http://samplecompany.com/tasks/23432/');
$object->setProperty('title','Sample task.');
$object->setProperty('content','...');
$object->addObjectType('http://samplecompany.com/activity/schema/1.0/task');
$object->addObjectType('http://activitystrea.ms/schema/1.0/note');
$object->setProperty('link','http://samplecompany.com/tasks/23432/');

// Define the action's author
$author = new ActivityStreamsAuthor();
$author->setProperty('name','Roger Taylor');
$author->setProperty('uri','http://samplecompany.com/people/Roger+Taylor/');

// Define the overall entry, adding the object, verbs and author
$entry = new ActivityStreamsEntry();
$entry->addVerb("http://samplecompany.com/activity/schema/1.0/complete");
$entry->addVerb("http://activitystrea.ms/schema/1.0/update");
$entry->title = "Roger Taylor completed a task.";
$entry->id = 'http://samplecompany.com/tasks/activity/23432/3242345/';
$entry->addObject($object);
$entry->setAuthor($author);

// Add the entry to the stream
$stream->addEntry($entry);

// Echo the stream
header('Content type: text/xml');
echo $stream;

リスト 10 のコードは、アクティビティー・ストリームの構造化バージョンを維持しているため、標準のオブジェクト指向の PHP メソッドとプロパティー呼び出しによってクエリーを実行することができます。フィードを表示するために echo が呼び出されると、各オブジェクトの内部 __toString() マジック・メソッドが呼び出されて、フィードが XML としてレンダリングされます。表示するのが XML ファイルであることをブラウザーに伝えるため、Content type: text/xml ヘッダーが最初に送信されます。


Activity Streams フィードの構文解析

PHP では、あらゆる種類の XML フィードを極めて簡単に構文解析することができます。フィードを構文解析するには、以下の組み込み SimpleXML 関数を使って構造をロードするだけのことです。

PHP での構文解析

Elliotte Rusty Harold の記事「PHP での SimpleXML 処理」では、Atom を含めた整形式 XML を PHP で構文解析する方法についてわかりやすく概説しています。

  • Simplexml_load_file($filename) は、ファイルから構造化 XML をロードします。
  • Simplexml_load_string($filename) は、ストリングから構造化 XML をロードします。

ActivityStreams クラスには、いろいろと明らかな修正案が考えられます。その 1 つは、子クラスのそれぞれを、組み込み PHP クラス SimpleXMLElement を継承する単一の汎用 ActivityStreamsElement クラスに統合することです。こうすれば、SimpleXML を呼び出すだけで、XML のフィードを処理してハンドラー・オブジェクトに返すことができます。

$activityStream = simplexml_load_string($xmlFeed, "ActivityStreamsElement");

しかし、SimpleXML の構文解析関数によって返されるデフォルト値であるストリームを、構造化された一連の SimpleXMLElement として処理するのは、配列内の要素をループ処理するだけの簡単なことです (リスト 11 を参照)。ただし注意する点として、Atom 名前空間と ActivityStreams 名前空間の両方を参照するようにしてください。

リスト 11. SimpleXML Atom フィードでの要素のループ処理
$activityStream = simplexml_load_string($stream);
$activityStream =  $activityStream->children('http://www.w3.org/2005/Atom');
if (is_array(!$activityStream->entry) && sizeof($activityStream->entry)) {
    foreach($activityStream->entry as $entry) {
        // Handle entry
    }
}

エントリー、エントリー内のオブジェクト、作成者などを処理する再帰関数を開発することもできます。Activity Streams フィードは、その親である Atom フィードと同じように、簡単に構文解析できて、さまざまな目的に使用できる単純な XML ファイルです。


まとめ

RSS に対するソーシャル Web アプリケーションの答えとして登場した Activity Streams フォーマットは、単純で、開発を容易にするだけでなく、広範なコンテキストで大きな威力を発揮します。企業という設定では、Activity Streams を拡張してセキュリティーを強化し、さらに巧みな機能を提供できる可能性が無数にあります。さまざまなビジネス活動を扱うために特化したオブジェクトと動詞のタイプを作成できるだけでなく、OAuth などの技術を使ってストリームに署名を付け、企業活動をアクセス権に基づいて表示するカスタム・ビューを作成することもできます。さらに、推奨されている Atom Media エクステンションを使えば、写真、動画および音声ファイル、そしてビジネス・プレゼンテーションなどのメディア・アイテムを Activity Streams フィードに組み込むことができます。


ダウンロード

内容ファイル名サイズ
Article source codeActivityStreamsEncoder.zip2KB

参考文献

学ぶために

  • Activity Streams: Activity Streams 標準の更新内容については、この信頼できる情報源にアクセスしてください。
  • DiSo Project: DiSo Project の詳細を学んでください。このプロジェクトでは、分散ソーシャル Web のためのオープンで一般的かつ相互運用可能なビルディング・ブロックの作成を促進することを目的としています。
  • Adding richness to activity streams」(Chris Messina 著、2008年6月): Activity Streams を世間に紹介したブログ投稿を読んでください。
  • PHP で Atom フィードを作成する」(Brian M. Carey 著、developerWorks、2009年7月): PHP を使用して Atom フィードを作成する方法を初心者にもわかりやすく説明しています。
  • PHP での SimpleXML 処理」(Elliotte Rusty Harold 著、developerWorks、2006年10月): PHP を使用して (Atom も含めた) XML フィードを処理する方法を手ほどきしている記事です。
  • Atom: ウィキペディアで Atom 仕様の概要を調べてください。
  • RFC 4827 - The Atom Syndication Format: Atom 仕様を読んで、フィードとして知られる関連情報のリストを記述する、この XML ベースの文書フォーマットに関する詳細を学んでください。
  • RFC 3339 - Date and Time on the Internet: Timestamps: Atom で使用する日付/時刻の仕様を調べてください。
  • Atom ウィキ: 公式 Atom 資料を調べてください。
  • PHP チュートリアル: PHP の基本を学んでください。
  • 無料の developerWorks チュートリアルに登録して、PHP でのプログラミング方法を学んでください。
    • Learning PHP, Part 1」(Tyler Anderson、Nicholas Chase 共著、developerWorks、2002年6月): HTML フォームおよびデータベース接続の観点から PHP の基本を学びます。
    • Learning PHP, Part 2」(Tyler Anderson、Nicholas Chase 共著、developerWorks、2002年6月): ファイルをアップロードする方法と、XML データの作成、操作、読み取り方法を学びます。
    • Learning PHP, Part 3」(Tyler Anderson、Nicholas Chase 共著、developerWorks、2002年7月): ファイルの配信方法、そしてオブジェクトのメソッドと例外を作成する方法を学びます。
  • PHP project resources: PHP 開発者向けに用意された、この広範な developerWorks リソースを調べてください。
  • My developerWorks: developerWorks のエクスペリエンスを自分流にカスタマイズしてください。
  • IBM XML 認定: XML や関連技術の IBM 認定技術者になる方法について調べてください。
  • XML technical library: 広範な技術に関する記事とヒント、チュートリアル、標準、そして IBM Redbooks については、developerWorks XML ゾーンを参照してください。
  • developerWorks の Technical events and webcasts: これらのセッションで最新情報を入手してください。
  • Twitter での developerWorks: 今すぐ登録して developerWorks のツイートをフォローしてください。
  • developerWorks podcasts: ソフトウェア開発者向けの興味深いインタビューとディスカッションを聞いてください。

製品や技術を入手するために

  • PHP: PHP を入手してください。この記事の例に従うには、バージョン 5 以降が必要です。
  • IBM 製品の評価版: DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を体験するには、評価版をダウンロードするか、IBM SOA Sandbox のオンライン試用版を試してみてください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Open source
ArticleID=500062
ArticleTitle=ソーシャル・オブジェクトを Atom フォーマットで表現する
publish-date=06152010