Blogger Data API を使用して Blogger のコンテンツを PHP アプリケーションに統合する

PHP と高度な Blogger Data API を使用して Blogger からブログ記事を取得し、Blogger にブログ記事を追加する

Blogger は (米国で) 人気のある無料のブログ・プラットフォームであり、このプラットフォームを使用することで、ユーザーは WYSIWYG 編集インターフェースによって独自のブログを作成したり、メッセージやニュースを投稿したりすることができます。REST ベースの Blogger Data API を使用すると、XML 準拠の任意のプログラミング・ツールキットを使用して Blogger のコンテンツにアクセスすることができます。この記事では、Blogger Data API と Zend Framework の Zend_Gdata コンポーネントを使用してブログ・コンテンツの一覧を表示する方法、ブログ記事を追加または編集する方法、ブログ・コメントを操作する方法などについて学びます。そして最後に、Blogger API の強力さを示す単純なアプリケーションを作成します。

Vikram Vaswani, Founder, Melonfire

Photo of Vikram VaswaniVikram Vaswani は、オープンソースのツールと技術を専門とするコンサルティング・サービス会社、Melonfire の創業者で、現在 CEO を務めています。彼は、『Zend Framework: A Beginners Guide』および『PHP: A Beginners Guide』の著者でもあります。



2011年 11月 04日

はじめに

皆さんは Blogger について聞いたことがあるかもしれません。Blogger は無料のブログ・プラットフォームで、このプラットフォームを使用することで任意のトピックに関する個人的なブログを作成したり、ブログ記事を公開したりすることができます。1999年に登場した Blogger は、最も初期に登場した Web 上のブログ・プラットフォームの 1 つです。その後 Blogger は Google に買収され、Google の一連の無料サービスの中に統合されています。

よく使われるブログ・アプリケーション

Blogger はよく使われるブログ・プラットフォームですが、ブログ・プラットフォームの選択肢は他にもたくさんあります。例えば、IBM Connections にはブログ機能が統合されています。よく使われる他のブログ・ソフトウェアの選択肢として、Wordpress、Drupal、Typepad などがあります。

Blogger を使用すると、特別な技術知識のない人も独自のブログを作成し、管理することができます。Blogger には以下のような特徴があります。

  • 定義済みのテンプレートやレイアウトがいくつか用意されています。
  • コメント機能やアクセス制御機能をサポートし、モバイル機器にも対応しています。
  • コンテンツの共有と収益化のために、他のサービス (Twitter や Google AdSense など) と緊密に統合されます。

要するに Blogger には、技術的な詳細を気にせずにブログを公開するために必要なすべてが用意されているのです。

よく使われる頭文字語

  • API: Application Programming Interface
  • HTML: HyperText Markup Language
  • HTTP: HyperText Transfer Protocol
  • REST: REpresentational State Transfer
  • RSS: Really Simple Syndication
  • URL: Uniform Resource Locator
  • WYSISYG: What You See Is What You Get
  • XML: Extensible Markup Language

しかし Blogger はユーザーにとって興味深いだけではありません。他の多くの Google のサービスと同様、Blogger には開発者用の API があり、この API を使用して Blogger サービスの内部にアクセスし、コンテンツを抽出して独自のカスタム・アプリケーションやマッシュアップを作成することができます。また、XML を扱える任意の開発ツールキットを使用して、REST モデルに従う Blogger Data API を利用することができます。Blogger Data API には、私の好きな PHP 用のライブラリーも含め、多くの一般的なプログラミング言語用のクライアント・ライブラリーが用意されています。

この記事では Blogger Data API の概要と、Blogger のコンテンツを PHP アプリケーションに統合して使用する方法について説明します。具体的には、以下の内容について多くの例を示しながら説明します。

  • Blogger Data API に接続する方法と Blogger Data API での認証方法
  • ブログの一覧とブログ・フィードを取得する方法
  • コンテンツを追加、更新、削除する方法
  • ブログ・コメントを扱う方法

重要な概念

PHP コードの説明に入る前に、このセクションでは Blogger Data API の概要を説明します。あらゆる REST ベースのサービスと同様、Blogger Data API は XML 形式の入力引数を 1 つ以上含む HTTP リクエストを受け付け、XML 形式のレスポンスを返します。このレスポンスは XML 対応の任意のクライアントで構文解析することができます。Blogger API を使用する場合、レスポンスは必ず Atom フィードまたは RSS フィードで構成され、要求された情報はそのフィードの中に含まれています。

Blogger にはパブリック・フィードとプライベート・フィードの両方があります。パブリック・フィード (例えば、ブログ内にある記事の一覧など) にアクセスする場合には、認証は必要ありませんが、プライベート・フィードにアクセスする場合には、認証が必要です。例えばプライベート・フィードへのアクセスでは、ブログ記事やコメントに追加や更新を行う場合に認証が必要です。この記事で取り上げる例では両方のタイプのフィードについて説明します。

この記事を最大限に利用するためには、Blogger アカウントを作成し、少なくとも 1 つの記事を含むブログを 1 つ用意する必要があります。ブログや記事がまだない場合には、Blogger にログインし (「参考文献」を参照)、新しいブログを作成し、テスト用の新しい記事をそのブログに追加します。ログインしたら、Web ブラウザーで http://www.blogger.com/feeds/default/blogs という URL にアクセスしてみてください。するとリスト 1 のような内容が表示されるはずです。

リスト 1. Blogger のメタフィード
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' 
 xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
  <id>tag:blogger.com,1999:user-12345USERIDHERE12345.blogs</id>
  <updated>2011-09-02T03:35:34.547Z</updated>
  <title type='text'>V Vaswani's Blogs</title>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
   href='http://www.blogger.com/feeds/12345USERIDHERE12345/blogs'/>
  <link rel='self' type='application/atom+xml' 
    href='http://www.blogger.com/feeds/12345USERIDHERE12345/blogs'/>
  <link rel='alternate' type='text/html' 
    href='http://www.blogger.com/profile/12345USERIDHERE12345'/>
  <author>
    <name>V Vaswani</name>
    <email>noreply@blogger.com</email>
  </author>
  <generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>
  <openSearch:totalResults>1</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
  <entry>
    <id>tag:blogger.com,1999:user-12345USERIDHERE12345.blog
     -12345BLOGIDHERE12345</id>
    <published>2008-02-19T23:30:41.755-08:00</published>
    <updated>2011-09-01T04:01:19.669-07:00</updated>
    <title type='text'>V Vaswani's Blog</title>
    <summary type='html'></summary>
    <link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/
     12345USERIDHERE12345/blogs/12345BLOGIDHERE12345'/>
    <link rel='alternate' type='text/html' href='http://vvaswani.blogspot.com/'/>
    <link rel='http://schemas.google.com/g/2005#feed' 
     type='application/atom+xml' 
     href='http://vvaswani.blogspot.com/feeds/posts/default'/>
    <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/default'/>
    <link rel='http://schemas.google.com/blogger/2008#template' 
     type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/template'/>
    <link rel='http://schemas.google.com/blogger/2008#settings' 
     type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/settings'/>
    <author>
      <name>V Vaswani</name>
      <email>noreply@blogger.com</email>
    </author>
    <gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' 
     name='IS_PUBLIC_BLOG' value='true'/>
    <gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' 
     name='PICASAWEB_ALBUM_ID' value='0'/>
  </entry>
</feed>

リスト 1 のメタフィードには、現在認証されているユーザーに関連付けられたすべてのブログの一覧が含まれています。メタフィードには、ルート要素としての <feed> 要素が最初にあります。<feed> 要素には以下の要素が含まれています。

  • <link> 要素 (そのフィードのさまざまなバージョンの URL を含んでいます)
  • <author> 要素 (アカウントの所有者を規定します)
  • <openSearch> 要素 (サマリー統計を含んでいます)

一番外側の <feed> 要素には 1 つ以上の <entry> 要素が含まれており、各 <entry> 要素が 1 つのブログを表します。各 <entry> には、各ブログに関する詳しい内容 (タイトル、説明、作成日、最終更新日、作成者など) と一連のフィードへのリンク (ブログ記事、ブログのテンプレート、ブログの設定などへのリンク) が含まれています。

リスト 1 で、各ブログには一意の識別子、つまりブログ ID が関連付けられています。ブログ ID は、そのブログ専用のフィードの URL を作成するために使用されます。例えば、ある特定のブログの記事フィードを検索するためには、<link rel='http://schemas.google.com/g/2005#post' ... /> 要素の中で指定される URL を使用します。リスト 2 は記事フィードの例を示しています。

リスト 2. Blogger の記事フィード
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' 
 xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' 
 xmlns:georss='http://www.georss.org/georss' 
 xmlns:thr='http://purl.org/syndication/thread/1.0'>
  <id>tag:blogger.com,1999:blog-12345BLOGIDHERE12345</id>
  <updated>2011-09-01T21:06:44.240-07:00</updated>
  <title type='text'>V Vaswani's Blog</title>
  <subtitle type='html'></subtitle>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
   href='http://vvaswani.blogspot.com/feeds/posts/default'/>
  <link rel='self' type='application/atom+xml' 
   href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/default'/>
  <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' 
   href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/default'/>
  <link rel='alternate' type='text/html' href='http://vvaswani.blogspot.com/'/>
  <author>
    <name>V Vaswani</name>
    <email>noreply@blogger.com</email>
  </author>
  <generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>
  <openSearch:totalResults>3</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
  <entry>
    <id>tag:blogger.com,1999:blog-12345BLOGIDHERE12345.post-
     12345POSTIDHERE12345</id>
    <published>2011-09-01T03:34:00.001-07:00</published>
    <updated>2011-09-01T21:06:44.258-07:00</updated>
    <title type='text'>My Third Post</title>
    <content type='html'>This is my third post
    <br /></content>
    <link rel='replies' type='application/atom+xml' 
     href='http://vvaswani.blogspot.com/feeds/12345POSTIDHERE12345/comments/default'
     title='Post Comments'/>
    <link rel='replies' type='text/html' 
     href='https://www.blogger.com/comment.g?
     blogID=12345BLOGIDHERE12345&postID=12345POSTIDHERE12345' 
     title='0 Comments'/>
    <link rel='edit' type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/
     default/12345POSTIDHERE12345'/>
    <link rel='self' type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/
     default/12345POSTIDHERE12345'/>
    <link rel='alternate' type='text/html' 
     href='http://vvaswani.blogspot.com/2011/09/my-third-d.html' 
     title='My Third Post'/>
    <author>
    <name>V Vaswani</name>
    <email>noreply@blogger.com</email>
    </author>
    <thr:total>0</thr:total>
  </entry>
  ...
</feed>

リスト 2 を見ると、記事フィードに一連の <entry> 要素が含まれ、各 <entry> 要素がそのブログの 1 つの記事を表すことがわかります。各 <entry> には以下の内容が含まれています。

  • 記事のタイトル、コンテンツ、公開日
  • 記事の公開 URL へのリンク、記事の編集 URL へのリンク、コメント・フィードの編集 URL へのリンク。これらのフィードと Blogger Data API を使用することで、記事、またはその記事に対するコメントを表示したり編集したりすることができます。

また各記事には記事 IDと呼ばれる一意の識別子があり、この ID はエントリーの <id> 要素の中に含まれています。<id> 要素はブログ ID と記事 ID の両方を含む複合ストリングであり、形式は tag:blogger.com,1999:blog-BLOGID.post-POSTID のようになっています。例えば tag:blogger.com,1999:blog-1234.post-6789 という識別ストリングでは、ブログ ID は 1234 であり、記事 ID は 6789 です。


ブログと記事を取得する

API を使用してブログ・フィードと記事フィードにアクセスする方法を理解できたので、同じことを PHP アプリケーションの中から試してみましょう。リスト 12 のフィードを生成するためには、まず Google アカウントを使用して手動で Blogger にログインします。PHP アプリケーションの中からフィードを取得して処理するには、手動の場合と同じ認証タスクをプログラムで実行する必要があります。

手動による認証は非常に面倒な作業であり、典型的な認証トランザクションの際に起こり得る多様なシナリオに対応するために、大量のコードが必要です。幸いなことに、Zend Framework には Zend_Gdata が含まれています。Zend_Gdata は PHP アプリケーションに Google Data API を統合しようとする開発者のために、専用に設計された PHP クライアント・ライブラリーです。Zend_Gdata には、Google Data API に対するオブジェクト指向の便利なインターフェースが用意されています (Zend_Gdata のダウンロードに関しては「参考文献」のリンクを参照)。Zend_Gdata には認証などの一般的なタスクの大部分がカプセル化されており、開発者はアプリケーションのコア機能に専念することができます。

Zend の Gdata ライブラリーをインストールしたら、リスト 3 を見てください。リスト 3 を見ると、リスト 1 のフィードを処理する方法と、そのフィードを変換し、Blogger で認証されたユーザーのブログをすべて Web ページ上に一覧表示する方法がわかります。

リスト 3. ブログを一覧表示する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // get list of all blogs
  $query = new Zend_Gdata_Query('http://www.blogger.com/feeds/default/blogs');
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Blogs</h2>
    <ul>
      <?php foreach ($feed as $entry): ?>      
      <li>
        <a href="<?php 
         echo $entry->getLink('alternate')->getHref(); ?>">
         <?php echo $entry->getTitle(); ?> 
        </a>          
      </li>
      <?php endforeach; ?>
    </ul>  
  </body>
</html>

リスト 3 は Zend クラス・ライブラリーをロードし、Zend_Gdata サービス・クラスのインスタンスを初期化しています。Zend_GdataZend_Http_Client オブジェクトを使用しており、ユーザー認証に必要な情報はこのオブジェクトに渡され、このオブジェクトを使用して Blogger サービスへの認証接続を開いています。また、この後 Blogger Data API とやり取りする場合にはすべて、この Zend_Gdata クラスが制御ポイントとなります。

認証接続を開いたら、getFeed() メソッドを使用してブログの一覧を取得します。getFeed()Zend_Gdata_Query オブジェクトを受け付け、このオブジェクトにブログの一覧のフィードの URL が渡されます。getFeed() API 呼び出しに対するレスポンスはリスト 1 と同じような XML フィードであり、この XML フィードが構文解析され、PHP オブジェクトに変換されます。フィードの中のエントリーは配列要素として表現されるため、以下のようなことができます。

  • フィードに対して繰り返し処理を実行する
  • 個々のブログの名前と URL を取得する
  • ブログの名前と URL を書式設定して Web ブラウザーに表示する

図 1 は表示される出力を示しています。

図 1. ユーザーのブログを表示した Web ページの例
ユーザーのブログを表示した Web ページのスクリーン・キャプチャー

先ほど触れたように、Blogger サービス内の各ブログと記事には一意の ID があります。ブログの一意の ID がわかると、そのブログに対応するブログ・フィードの URL を生成することができます (ブログ・フィードには、そのブログ内のすべての記事の一覧が含まれています)。リスト 4 に、そうしたブログ・フィードを Zend_Gdata クライアント・ライブラリーを使用して取得、処理するためのプロセスを示します。

リスト 4. ブログ記事を一覧表示する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // get list of all posts in blog feed
  $query = new Zend_Gdata_Query(
   'http://www.blogger.com/feeds/YOUR-BLOG-ID-HERE/posts/default');
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Posts</h2>
    <ul>
      <?php foreach ($feed as $entry): ?>      
      <li>
        <a href="<?php 
         echo $entry->getLink('alternate')->getHref(); ?>">
            <?php echo $entry->getTitle(); ?> 
        </a>          
      </li>
      <?php endforeach; ?>
    </ul>  
  </body>
</html>

リスト 3 の場合と同様、リスト 4 は最初に Zend ライブラリーを初期化し、認証済みの Zend_Gdata サービス・オブジェクトを作成します。ブログ ID を使用してブログ・フィードの URL が作成され、この URL が Zend_Gdata_Query オブジェクトに変換されて getFeed() メソッドに渡されます。作成されるフィードは通常の方法で構文解析されて処理され、指定されたブログ内にあるすべての記事の一覧が生成されます。図 2 は出力の例を示しています。

図 2. ユーザーのブログ記事の一覧を表示した Web ページ
ユーザーのブログ記事の一覧を表示した Web ページのスクリーン・キャプチャー

リスト 3リスト 4 を組み合わせると、認証されたユーザーのすべてのブログと、各ブログ内の記事の一覧を生成することができます。リスト 5 は、リスト 3 とリスト 4 を組み合わせた結果のコードを示しています。

リスト 5. ブログとブログ記事を一覧表示する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // create array
  $data = array();
  
  // get list of all posts in all blog feeds
  $query1 = new Zend_Gdata_Query('http://www.blogger.com/feeds/default/blogs');
  $feed1 = $service->getFeed($query1);
  foreach ($feed1 as $entry1) {
    $arr = explode('-', (string)$entry1->getId());
    $id = $arr[2];
    $query2 = new Zend_Gdata_Query(
     'http://www.blogger.com/feeds/'.$id.'/posts/default');
    $feed2 = $service->getFeed($query2);
    $blogArray = array(
      'title' => (string)$entry1->getTitle(), 
      'uri' => (string)$entry1->getLink('alternate')->getHref(),
      'posts' => array()
    );
    foreach ($feed2 as $entry2) {
      $postArray = array(
        'title' => (string)$entry2->getTitle(), 
        'uri' => (string)$entry2->getLink('alternate')->getHref()
      );
      $blogArray['posts'][] = $postArray;
    }
    $data[] = $blogArray;
  }
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Blogs and Posts</h2>
    <div id="results">
      <?php foreach ($data as $d): ?>      
      <ul>      
        <li><a href="<?php echo $d['uri']; ?>">
        <?php echo $d['title']; ?></a></li>
          <ul>
          <?php foreach ($d['posts'] as $p): ?>      
            <li><a href="<?php echo $p['uri']; ?>">
            <?php echo $p['title']; ?></a></li>
          <?php endforeach; ?>
          </ul>
      </ul>
      <?php endforeach; ?>
    </div>  
  </body>
</html>

リスト 5 は最初にブログのメタフィードを要求し、そのメタフィード内のエントリーに繰り返し処理を行うことで各ブログの一意の ID を取得しています。次に、この ID を使用してブログの記事フィードの URL を作成し、この URL にリクエストを送信し、各記事のタイトルと URL を抽出する処理が行われます。これらの情報はすべて、ネストされた配列に格納されます (リスト 6)。

リスト 6. ネストされた配列
Array
(
  [0] => Array
  (
    [title] => V Vaswani's Blog
    [uri] => http://***.blogspot.com/
    [posts] => Array
    (
      [0] => Array
      (
        [title] => My Fourth Post
        [uri] => http://***.blogspot.com/2011/09/my-fourth-post.html
      )

      [1] => Array
      (
        [title] => My Third Post
        [uri] => http://***.blogspot.com/2011/09/my-third-d.html
      )

      [2] => Array
      (
        [title] => My Second Post
        [uri] => http://***.blogspot.com/2011/08/my-second-post.html
      )

      [3] => Array
      (
        [title] => My First Post
        [uri] => http://***.blogspot.com/2008/02/testing.html
      )
    )
  )

  [1] => Array
  (
    [title] => V Vaswani's Second Blog
    [uri] => http://***.blogspot.com/
    [posts] => Array
    (
      [0] => Array
      (
        [title] => My First Post in my Second Blog
        [uri] => http://***.blogspot.com/2011/09/my-first-post-in-my-second-blog.html
      )
    )
  )
)

配列が完全に生成されると、この配列に対して単純に繰り返し処理を実行し、ブログとブログ記事の一覧 (ネストされた形で表示されます) を作成することができます。図 3 は出力の例を示しています。

図 3. ユーザーのブログとブログ記事の一覧を表示した Web ページ
ユーザーのブログとブログ記事の一覧を表示した Web ページのスクリーン・キャプチャー

ブログ記事を追加する

Blogger Data API を使用すると、ブログ記事を取得する以外にも、認証済みユーザーが新しい記事をブログに追加するためのプログラムを作成することができます。そのためには新しい Zend_Gdata_App_Entry オブジェクトを作成し、そのオブジェクトにタイトルとコンテンツを設定したら、そのオブジェクトを記事フィードに POST 送信します。リスト 7 に、そのサンプル・コードを示します。

リスト 7. ブログ記事を追加する
<?php
if (isset($_POST['submit'])) {

  // load Zend Gdata libraries
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata');
  Zend_Loader::loadClass('Zend_Gdata_Query');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
  Zend_Loader::loadClass('Zend_Gdata_Feed');

  // set credentials for ClientLogin authentication
  $user = "your-username@gmail.com";
  $pass = "your-password";

  // set blog id
  $id = 'YOUR-BLOG-ID-HERE';

  try {
    // perform login 
    // initialize service object
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'blogger');
    $service = new Zend_Gdata($client);

    // create a new entry object
    // populate it with user input    
    $uri = 'http://www.blogger.com/feeds/' . $id . '/posts/default';
    $entry = $service->newEntry();
    $entry->title = $service->newTitle($_POST['title']);
    $entry->content = $service->newContent($_POST['body']);
    $entry->content->setType('text');

    // save entry to server
    // return unique id for new post
    $response = $service->insertEntry($entry, $uri);
    $arr = explode('-', $response->getId());
    $id = $arr[2];
    echo 'Successfully added post with ID: ' . $id;

  } catch (Exception $e) {
    die('ERROR:' . $e->getMessage());  
  }
}
?>
<html>
  <head></head>
  <body>
    <h2>Add New Post</h2>
    <form method="post">
      Title: <br/> <input type="text" name="title" 
       size="50" /> <br/>
      Body: <br/> <textarea name="body" cols="40" 
       rows="10"> </textarea> <br/>
      <input type="submit" name="submit" value="Post" />
    </form>
  </body>
</html>

リスト 7 のコードでは、ユーザーは単純な Web フォームからブログ記事のタイトルと本文を入力することができます。フォームが送信されると、このスクリプトは Zend クラス・ライブラリーを読み込んで、認証済みのサービス・オブジェクトを作成します。次に、そのサービス・オブジェクトの newEntry() メソッドを使用して新しい entry オブジェクトを作成し、ユーザーが入力した内容を基に、newTitle() メソッドと newContent() メソッドを使用してブログ記事のタイトルとコンテンツを設定しています。これらを設定した後、insertEntry() メソッドを使用して新しい記事を Google のサーバーに保存しています。

図 4 はフォームの例を示しています。

図 4. 新しいブログ記事を追加するための Web フォーム
新しいブログ記事を追加するための Web フォームのスクリーン・キャプチャー。このフォームには「Title (タイトル)」フィールドと「Body (本文)」フィールドがあります。

insertEntry() メソッドの戻り値は、新しく作成された記事を表すエントリーで、そのエントリーには記事の一意の ID が含まれています。この ID は抽出されて、新しい記事を追加した結果と一緒にページ上に表示されます。このエントリーが保存されると、新しい記事が公開ブログに表示され、そのブログのすべての API フィードにも新しい記事が含まれるようになります。


ブログ記事を編集、および削除する

Blogger Data API を使用して既存の記事を削除したり編集したりすることもできます。どちらの場合も、操作に対応する DELETE リクエストまたは PUT リクエストをその記事の編集 URL に送信する必要があります (リスト 2 の例を参照)。どちらの操作も、認証済みユーザー以外は実行することができません。

リスト 8 に、API を使用して既存のブログ記事を削除するコードを示します。ここでは既にブログの ID と記事の ID がわかっていることを前提としています。

リスト 8. ブログ記事を削除する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

// set blog and post ids
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // set URI for entry to delete
  // obtain from <link rel=edit ... />
  $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;
  $service->delete($uri);
  echo 'Successfully deleted post with ID: ' . $pid;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

リスト 8 では、指定されたブログ記事をサービス・オブジェクトの delete() メソッドを使用して削除しています。delete() メソッドは記事の編集 URL を受け付け、その URL に DELETE リクエストを送信します。その記事が削除されると、そのブログ記事は公開ブログに表示されなくなり、その記事を参照するどの API フィードにも含まれなくなります。

引き続き、ブログの ID と記事の ID がわかっているという前提の下、今度は API を使用して既存のブログ記事を更新するコードをリスト 9 に示します。

リスト 9. ブログ記事を更新する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

// set blog and post ids
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // set URI for entry to update
  // obtain from <link rel=self ... />
  $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;

  // get the existing entry
  // set new values
  // save it back
  $response = $service->get($uri);
  $entry = new Zend_Gdata_App_Entry($response->getBody());
  $entry->title = $service->newTitle("New title");
  $entry->content = $service->newContent("New content");
  $entry->content->setType('text');
  $service->updateEntry($entry);
  echo 'Successfully updated post with ID: ' . $pid;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

API を使用してブログ記事を更新するプロセスには 2 つのステップがあります。最初のステップでは、既存のブログ記事を取得して Zend_Gdata_App_Entry オブジェクトに変換する必要があります。そして次のステップで、newTitle()newContent() などのサービス・オブジェクトを使用してそのエントリーを更新し、updateEntry() メソッドを使用してそのエントリーをサーバーに保存します。

insertEntry() メソッドの場合と同じように、updateEntry() メソッドの戻り値はその記事を表すエントリーであり、その記事の一意の ID と記事のコンテンツが含まれています。そのエントリーが保存されると、更新された記事は公開ブログに表示され、そのブログを参照するすべての API フィードにも表示されます。


コメントを扱う

記事を追加、編集、削除できるのとまったく同じように、記事のコメントを追加、編集、削除することができます。リスト 2 で、各記事のエントリーに記事のコメント・フィードへのリンクが含まれていることに注意してください。新しいコメントを追加するためには、このコメント・フィードにエントリーを挿入するだけでよいのです。

リスト 10 は新しいコメントを記事に追加するプロセスを示しています。

リスト 10. 新しいコメントを追加する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

// set blog and post ids
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // create a new entry object
  // populate it with user input    
  $uri = "http://www.blogger.com/feeds/$bid/$pid/comments/default";
  $entry = $service->newEntry();
  $entry->content = $service->newContent('This is a very interesting post.');
  $entry->content->setType('text');

  // save entry to server
  // return unique id for new comment
  $response = $service->insertEntry($entry, $uri);
  $arr = explode('/', $response->getEditLink()->href);
  $id = $arr[8];
  echo 'Successfully added comment with ID: ' . $id;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

新しいコメントを追加する手順は、新しい記事を追加する場合とほとんど同じであり、唯一の違いはリクエストを POST 送信する宛先の URL のみです (この場合の宛先はコメント・フィードの URL です)。insertEntry() メソッドに対して返されるレスポンスは、新しく追加されたコメントを表すオブジェクトです。このオブジェクトは構文解析されて、一意のコメント ID が取得されます。後でそのコメントを削除する場合、このコメント ID が必要になります。

既にコメント ID がわかっているとすると、リスト 11 のコードと delete() メソッドを使用して、そのコメントをプログラムで削除することができます。

リスト 11. コメントを削除する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

// set blog, post and comment ids
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';
$cid = 'YOUR-COMMENT-ID-HERE';

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // set URI for entry to delete
  // obtain from <link rel=edit ... />
  $uri = "http://www.blogger.com/feeds/$bid/$pid/comments/default/$cid";
  $service->delete($uri);
  echo 'Successfully deleted comment with ID: ' . $cid;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

また、同じコメント・フィードの URL を使用して、ある記事に対するすべてのコメントの一覧を取得することもできます (リスト 12)。

リスト 12. コメントを一覧表示する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

// set blog and post ids
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // get list of all comments for post
  $uri = "http://www.blogger.com/feeds/$bid/$pid/comments/default/";
  $query = new Zend_Gdata_Query($uri);
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Comments</h2>
    <div id="results">
      <ul>
      <?php foreach ($feed as $entry): ?>      
        <?php $author = $entry->getAuthor(); ?>
        <li><?php echo $entry->getTitle(); ?> 
         - <?php echo $author[0]->getName(); ?> <br/>
        <?php echo date('d M Y H:i', strtotime($entry->getUpdated())); ?>
        </li>          
      <?php endforeach; ?>
    </ul>  
  </body>
</html>

サンプル・アプリケーション: コンテンツ管理システム

では、ここまで説明したすべての内容を実践するための簡単なアプリケーションとして、Blogger Data API の強力さを示す実際のアプリケーションを作成してみましょう。このサンプル・アプリケーションは Web ベースのコンテンツ・マネージャーです。このアプリケーションを使用することで、ユーザーは既存のブログ記事を表示したり、新しい記事を追加したり、既存の記事を編集または削除したりすることができます。編集はブラウザー・ベースの WYSIWYG エディターを使用して行われ、編集結果は Blogger Data API を使用して Blogger に送信されます。

まず、開発用のサーバーに TinyMCE JavaScript エディターをダウンロードしてインストールします (「参考文献」のリンクを参照)。続いて、リスト 13 のコードを含むスクリプトを作成します。

リスト 13. ブログ・コンテンツを管理する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// set credentials for ClientLogin authentication
$user = "your-username@gmail.com";
$pass = "your-password";

// set blog id
$bid = 'YOUR-BLOG-ID-HERE';

try {
  // perform login 
  // initialize service object
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // for add and edit operations
  if (isset($_POST['submit'])) {
    // if post id present
    // update post with new content
    if (isset($_POST['pid'])) {      
      $arr = explode('-', $_GET['pid']);
      $pid = $arr[2];
      $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;
      $response = $service->get($uri);
      $entry = new Zend_Gdata_App_Entry($response->getBody());
      $entry->title = $service->newTitle($_POST['title']);
      $entry->content = $service->newContent($_POST['body']);
      $entry->content->setType('text');
      $service->updateEntry($entry);
      echo 'Successfully updated post with ID: ' . $pid;    
    } else {
      // if post id not present
      // create a new post
      // populate it with user input    
      $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default';
      $entry = $service->newEntry();
      $entry->title = $service->newTitle($_POST['title']);
      $entry->content = $service->newContent($_POST['body']);
      $entry->content->setType('text');
      $response = $service->insertEntry($entry, $uri);
      $arr = explode('-', $response->getId());
      $id = $arr[2];
      echo 'Successfully added post with ID: ' . $id;  
    }
  }

  // for edit and delete operations
  if (isset($_GET['op'])) {
    // generate post URL
    $arr = explode('-', $_GET['pid']);
    $pid = $arr[2];
    $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;
    switch($_GET['op']) {
      case 'delete':
        // delete post
        $service->delete($uri);
        echo 'Successfully deleted post with ID: ' . $pid;      
        break;
      case 'edit':
        // retrieve post for display in edit form
        $response = $service->get($uri);
        $entry = new Zend_Gdata_App_Entry($response->getBody());
    }
  }
  
  // get list of all posts in blog feed
  $query = new Zend_Gdata_Query(
   'http://www.blogger.com/feeds/'.$bid.'/posts/default');
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head>
    <script type="text/javascript" 
     src="tinymce/jscripts/tiny_mce/tiny_mce.js"></script>
    <script type="text/javascript">
    tinyMCE.init({
            mode : "textareas",
            theme : "advanced",
            theme_advanced_buttons1 : "bold,italic,underline,|,justifyleft,
             justifycenter,justifyright,|,code,preview,|,forecolor,backcolor,|,sub,sup,
             |,fontsizeselect",
            theme_advanced_buttons2 : "cut,copy,paste,|,bullist,numlist,|,outdent,indent,
             |,undo,redo,|,link,unlink,anchor,image,|,removeformat",
            theme_advanced_buttons3 : "",      
            theme_advanced_toolbar_location : "top",
            theme_advanced_toolbar_align : "left",
            theme_advanced_statusbar_location : "bottom",
            theme_advanced_resizing : true
    });

    </script>
  </head>
  <body>
    <h2>View Posts</h2>
    <ul>
    <?php foreach ($feed as $e): ?>  
      <li><?php echo $e->getTitle(); ?> <br/>
      <a href="<?php 
      echo $e->getLink('alternate')->getHref(); ?>">View</a> 
       | <a href="?op=edit&pid=<?php echo $e->getId(); ?>">Edit</a>
       | <a href="?op=delete&pid=<?php echo $e->getId(); ?>">Delete
       </a>
      </li>
    <?php endforeach; ?>
    </ul>
    <a href="<?php echo $_SERVER['PHP_SELF']; ?>">
     Add a new post</a>
    <?php if (isset($_GET['op']) && $_GET['op'] == 'edit'): ?>
    <h2>Edit Post</h2>
    <form method="post">
      Title: <br/> <input type="text" name="title" size="50" 
       value="<?php echo $entry->title; ?>" /> <br/>
      Body: <br/> <textarea name="body" cols="40" 
       rows="10"><?php echo $entry->content; ?></textarea> <br/>
      <input type="hidden" name="pid" 
       value="<?php echo $entry->id; ?>" />
      <input type="submit" name="submit" value="Post" />
    </form>
    <?php else: ?>
    <h2>Add New Post</h2>
    <form method="post">
      Title: <br/> <input type="text" name="title" 
       size="50" /> <br/>
      Body: <br/> <textarea name="body" cols="40" 
       rows="10"> </textarea> <br/>
      <input type="submit" name="submit" value="Post" />
    </form>
    <?php endif; ?>
  </body>
</html>

上記のコードは複雑に見えるかもしれませんが、これまでに説明したコードの前後に条件文がいくつか付け加えられているにすぎません。このコードは以下のように分解するとわかりやすいかもしれません。

  • このスクリプトはまず Zend クラス・ライブラリーをロードし、認証のためのクレデンシャルを設定しています。また、ブログの ID も定義しています。それ以降の操作はすべて、指定されたブログに対してのみ行われます。
  • リクエスト・パラメーターが何もないとすると、スクリプトは Blogger API に接続し、指定されたブログ内のすべての記事の一覧を要求します。次に、要求に対する結果として取得したフィードを処理し、記事の一覧を HTML のリストとして表示します。

    各記事には、その記事を View (表示)、Edit (編集)、Delete (削除) するための 3 つのリンクがあります。「View (表示)」リンクは、その記事の公開 URL を指定します。「Edit (編集)」リンクと「Delete (削除)」リンクは単純に再度スクリプトを呼び出し、選択された記事の ID を GET リクエスト・パラメーターとしてスクリプトに渡します。

  • 現在の記事の一覧を生成した後、スクリプトはユーザーが新しい記事を追加するための Web フォームも生成します。このフォームには、1 行のテキスト入力フィールド (記事のタイトル用) と、複数行のテキスト領域 (記事の本文用) があります。

    TinyMCE エディターもページをロードした際に初期化されます。このエディターがテキスト領域を自動変換し、フォーマット設定コントロールとハイパーリンク・コントロールを備えた WYSIWYG テキスト編集フィールドにします。

  • 次に何が起こるかは、ユーザーがどの操作を行うかに依ります。
    ユーザーが選択する操作実行される内容
    新しい記事の追加Web フォームにコンテンツが入力されて、送信されると、スクリプトは newEntry() メソッドを使用して新しいエントリー・オブジェクトを作成し、送信された入力をそのオブジェクトに追加し、insertEntry() メソッドを使用してそのオブジェクトをブログに保存します。
    既存の記事の削除選択された記事の ID がリクエスト URL から取得され、ブログの ID と記事の ID を使用して記事フィードの URL が作成されます。そしてその記事はサービス・オブジェクトの delete() メソッドを使用して削除されます。
    既存の記事の編集選択された記事の ID がリクエスト URL から取得され、ブログの ID と記事の ID を使用して記事フィードの URL が作成されます。そしてサービス・オブジェクトの get() メソッドを使用してその記事が取得されると、編集用の Web フォームにその記事のコンテンツが入力され、記事の一意の ID が含まれる隠しフィールドも用意されます。

    ユーザーがコンテンツに変更を加えて再度フォームを送信すると、隠しフィールドに含まれる記事の ID と updateEntry() メソッドを使用して既存の記事を特定し、その記事を更新します。

単純にするために、このスクリプトには入力内容の検証が含まれていません。本番環境では、検証機能を追加し、ユーザーから収集したデータの完全性と有効性を確認する必要があります。

図 5 はコンテンツ管理システムの例を示しています。

図 5. ブログ・コンテンツを管理するインターフェース
ブログ・コンテンツを管理するインターフェースのスクリーン・キャプチャーe

まとめ

この記事では、Blogger Data API と Zend Gdata クライアント・ライブラリーを使用して Blogger によるブログ記事を PHP アプリケーションに直接統合する方法について学びました。そして Blogger フィード・フォーマットを紹介しました。また、以下の内容についても学びました。

  • ブログ、記事、コメントを取得する方法
  • 記事を追加、編集、削除する方法
  • コメントを表示、追加、削除する方法

Blogger API にはフォーマットに依存しない高度なメカニズムが用意されているため、公開されているブログ・コンテンツを任意の Web アプリケーションに容易に統合することができます。マッシュアップを作成する場合、あるいは Blogger に対する独自のカスタム・インターフェースを作成する上で、Blogger API は非常に優れたツールです。いつか Blogger API を試し、どんなことができるのかを確認してみてください。

参考文献

学ぶために

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

  • Zend Framework: Zend をダウンロードしてください。Zend のベースには、単純さ、オブジェクト指向のベスト・プラクティス、企業にとって利用しやすいライセンス、厳格にテストされたアジャイルなコード・ベースがあります。
  • TinyMCE エディター: プラットフォームに依存しない Web ベースの JavaScript HTML WYSIWYG エディターを入手してください。
  • IBM 製品の評価版: IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2、Lotus、Rational、Tivoli、および WebSphere が提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。

議論するために

コメント

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=768335
ArticleTitle=Blogger Data API を使用して Blogger のコンテンツを PHP アプリケーションに統合する
publish-date=11042011