Google+ のアクティビティー・ストリームを検索し、PHP アプリケーションと統合する

Google+ API と PHP を使用して Google+ の投稿記事を取得し、ユーザーを検索する

Google の新しいソーシャル・ネットワーキング・サービス、Google+ を使用すると、ユーザーは近況メッセージや最近の出来事を投稿することができます。さらに Google+ API を使用すると、それらのメッセージにアクセスしたり、メッセージを検索したりすることができます。この記事では Google+ API の基本を説明します。例を示しながら、Google+ API を PHP と組み合わせて動的な Web アプリケーションを作成する方法について説明します。

はじめに

ソーシャル・ネットワーキングの世界に新たに登場した Google+ は、ソーシャル・ネットワークを構築しようとする Google の最新の試みであり、ユーザーは Google+ を利用することで、最近の出来事やファイルを友だちと共有したり、友だちとコミュニケーションをとったりするのが容易になります。Google+ は見事に人々の関心を呼んでいるようであり、伝えられるところによれば、2011年 12月時点で毎日 625,000 人が新たに Google+ に登録しており、ユーザーの合計は 6,200 万人に達しています (「参考文献」を参照)。

頻繁に使用される略語

  • API: Application Programming Interface
  • HTTP: HyperText Transfer Protocol
  • JSON: JavaScript Object Notation
  • PHP: Hypertext Preprocessor

Google+ には Web 開発者を夢中にさせるだけのものがあります。Google が提供する他の多くのサービスと同様、Google+ には開発者用 API が用意されており、この API を利用することで、ユーザーが生成したコンテンツに対して独自のカスタム・アプリケーションからアクセスすることができます。また、Google+ API の出力は JSON なので、ほとんどのプログラミング・ツールキットと容易に統合することができます。

この記事では Google+ API について説明します。そのために、Google+ API を使用して Google+ からコンテンツを抽出し、そのコンテンツを PHP アプリケーションに統合する方法を説明します (これは楽しい作業なので、皆さんはこの API で遊ぶことに熱中してしまう可能性があることを事前に警告しておきます)。


API の基本

Google+ を使用するアプリケーションの開発を開始する前に、この API がどのように動作するのかを理解する必要があります。Google+ API は HTTP 上で動作し、指定のエンドポイントに HTTP リクエストが送信されることを前提にしています。HTTP リクエストを受信すると、Google+ API のサーバーは要求されたデータを含む JSON フィードによって、リクエストに含まれる照会に応答します。すると、サーバー・サイドのプログラミング言語 (PHP や Perl) またはクライアント・サイドのツールキット (jQuery や mooTools) のいずれかを使用してこの応答に含まれるデータを構文解析し、コンテンツを抽出して Web ページに統合することができます。

Google+ を使用するアプリケーションの開発を開始するには、まず以下の 2 つのことを行う必要があります。

  1. Google+ アカウントを設定する
    1. Google アカウントにログインし、メイン・メニューの「+You」リンクを使用して Google+ アカウントを登録します。
    2. Google のアカウント設定ページに進み、皆さん個人の Google プロフィールの URL を取得します。この URL に皆さんの Google ID も含まれています (図 1)。
    3. この ID に注意してください。この記事で説明するいくつかの例で、この ID が必要になります。
    図 1. Google ID が含まれる Google プロフィールの URL
    Google ID が含まれる Google プロフィールの URL
  2. Google+ アカウントで API にアクセスできるようにする
    1. Google APIs Console (コンソールへのリンクは「参考文献」を参照) で新しいプロジェクトを作成します。
    2. 新しいプロジェクトに対して Google+ API を有効にします。
    3. 自動生成された API キーが得られるので、そのキーを使用して Google+ API にアクセスします。このキーは Google APIs Console の API Access タブの下にあります (図 2)。
    4. この API キーを注意深くメモします。
    図 2. Google APIs Console で API アクセス・キーを取得する
    Google APIs Console で API アクセス・キーを取得する

OAuth を使用して Google+ API にアクセスすることもできます (OAuth については、この記事では説明しません)。

Google+ ID と API キーを取得したら、ブラウザーで API エンドポイント https://www.googleapis.com/plus/v1/people/ID/activities/public?key=API-KEY にアクセスしてみてください。その際、今取得した ID とキーの値で ID と API-KEY のプレースホルダーを置き換えることを忘れないでください。このリクエストに対するレスポンス (表示されるページのソース・コードの中でレスポンスを見ることができます) には、自分が Google+ に対して最近行った一連の投稿が含まれています。このレスポンスはリスト 1 のようなものです。なお、一意の ID はわからないようにしてあります。

リスト 1. JSON フォーマットで出力された Google+ のアクティビティー・フィードの例
{
 "kind": "plus#activityFeed",
 "etag": "ab49djslas22",
 "nextPageToken": "eJxtbiSnOTUova1kyV5Z7y",
 "selfLink": "https://www.googleapis.com/plus/v1/people/ID/activities/public?",
 "nextLink": "https://www.googleapis.com/plus/v1/people/ID/activities/
    public?maxResults=20&pageToken=",
 "title": "Plus Public Activity Feed for John Doe",
 "updated": "2012-01-17T06:05:03.277Z",
 "id": "tag:google.com,2010:/plus/people/ID/activities/public",
 "items": [
  {
   "kind": "plus#activity",
   "etag": "abc",
   "title": "Sleepy at work",
   "published": "2012-01-17T06:05:03.000Z",
   "updated": "2012-01-17T06:05:03.277Z",
   "id": "zab",
   "url": "https://plus.google.com/ID/posts/XgGBBbn",
   "actor": {
    "id": "ID",
    "displayName": "John Doe",
    "familyName": "Doe",
    "givenName": "John",
    "url": "https://plus.google.com/ID",
    "image": {
     "url": "https://lh5.googleusercontent.com/9HzARk/Cxo/photo.jpg?sz=0"
    }
   },
   "verb": "post",
   "object": {
    "objectType": "note",
    "content": "Sleepy at work",
    "originalContent": "",
    "url": "https://plus.google.com/ID/posts/XgGBBbn",
    "replies": {
     "totalItems": 0,
     "selfLink": "https://www.googleapis.com/plus/v1/activities/xys/comments"
    },
    "plusoners": {
     "totalItems": 0,
     "selfLink": "https://www.googleapis.com/plus/v1/activities/xys/people/plusoners"
    },
    "resharers": {
     "totalItems": 0,
     "selfLink": "https://www.googleapis.com/plus/v1/activities/xys/people/resharers"
    }
   },
   "provider": {
    "title": "Google+"
   },
   "access": {
    "kind": "plus#acl",
    "items": [
     {
      "type": "public"
     }
    ]
   }
  },
  {
  ...
  }
 ]
}

Google+ API はリクエストに対し、要求されたデータを含む JSON フィードで応答します。Google+ には以下のような興味深いフィードがいくつかあります。

  • アクティビティー・フィード: 特定のユーザーが投稿した一般公開記事がすべて含まれています。
  • 各アクティビティーに対するコメント・フィード: 特定のアクティビティーに対するユーザー・コメントのリストが含まれています。
  • パーソン・フィード: 指定されたキーワードまたはアクティビティーに一致するユーザーのリストが含まれています。

上記のフィードを取得するためには API キーまたは OAuth トークンによる認証が必要です。

フィード自体は JSON 文書のフォーマットをしており、最も外側のキーには結果セットのフィードのタイトルと、現在のページ (そして場合によると、次のページと前のページ) の URL が含まれています。items 配列には一連のリソースが含まれています。要求されるフィードに応じて、リソースはアクティビティーの場合やプロフィールの場合、あるいはコメントの場合があります。リソースの集合の各エントリーには、そのリソースに関する以下のような詳細が含まれています。

  • リソースの公開 URL
  • リソースの種類とリソースの ID
  • 作成者
  • 公開日

リソースの種類によっては、さらに情報が含まれる場合があります (アクティビティーの内容、プロフィールの説明、作成者の画像、コメントの数、共有および +1、添付とその内容など)。この記事の後の方で、これらすべての例について説明します。

現状では、Google+ API は読み取り専用です。Google+ API から情報を取得することはできますが、書き込み操作、つまり新しいアクティビティーやコメントの投稿、作成者のプロフィールや写真の更新、アクティビティーの削除などは、現在の Google+ API ではサポートされていません。

サードパーティーのアプリケーションで Google+ のコンテンツを使用する場合には、Google+ の利用規約が適用されます。皆さんのアプリケーションは Google+ の開発者ポリシーに従う必要があります。必要なすべてのルールに確実に従えるように、開発を開始する前に少し時間を割いてこれらの文書を読んでおくとためになります (「参考文献」を参照)。


アクティビティー・フィードを取得する

このセクションでは、Google+ API によって返されたデータを PHP アプリケーションに統合する方法について説明します。最も容易な方法は Zend Framework の Zend_Http_Client コンポーネントを使用する方法です。このコンポーネントを使用すると、HTTP リクエストの作成、送信、処理のプロセスを単純化することができます。リスト 2Zend_Http_Client を使用して Google+ API にリクエストを送信し、その結果を処理する方法を示しています。

リスト 2. Google+ のアクティビティー・フィードを処理する
<?php
// load Zend classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Http_Client');

// define user ID
$uid = 'YOUR-ID-HERE';

// define API key
$key = 'YOUR-API-KEY-HERE';

try {
  // get feed of user public activities
  // decode JSON response
  $client = new Zend_Http_Client(
    "https://www.googleapis.com/plus/v1/people/$uid/activities/public?key=$key"
  );
  $response = $client->request('GET'); 
  $result = json_decode($response->getBody());

  // iterate through response  
  echo '<h1>' . $result->title . '</h1>';
  echo count($result->items) . ' post(s) found. <br/>';
  echo '<ol>';
  foreach ($result->items as $entry) {
    echo '<li>';
    echo '<a href="' . $entry->url . '">' . $entry->title . '</a>';
    echo ' (' . date("d M Y h:i", strtotime($entry->published)) . ')';  
    echo '</li>';
  }
  echo "</ol>";
  
} catch (Exception $e) {
  echo 'ERROR:' . $e->getMessage();
}   
?>

リスト 2 では、最初に Zend クラス・ライブラリーを読み込み、Zend_Http_Client クラスのインスタンスを初期化しています。このクライアントを使用してユーザーの一般公開アクティビティー・フィードに対する GET リクエストを作成し、(リスト 1 の) API エンドポイント https://www.googleapis.com/plus/v1/people/[ID]/activities/public に送信しています。この場合のエンドポイントの URL の中に、ユーザーの Google ID と、Google APIs Console で生成された API キーの両方を含める必要があることに注意してください。

このリクエストに対する JSON レスポンスは PHP の json_decode() 関数を使用して構文解析され、PHP オブジェクトに変換されます (図 3)。

図 3. Google+ のアクティビティーのコンテンツを含む PHP オブジェクト
Google+ のアクティビティーのコンテンツを含む PHP オブジェクト

図 3 に示すオブジェクトのプロパティーをリスト 1 の JSON 文書のキーと値のペアと比較すると、この 2 つが対応していることがわかるはずです。これで、このオブジェクトの items 配列に対して繰り返し処理を行って個々のアクティビティーのデータ (アクティビティーのタイトル、投稿の URL、公開日など) を取得し、そのデータをフォーマット設定して Web ページとして表示することが容易に行えるようになります。

図 4 は表示したい出力のソース・コードの一例です。

図 4. Google+ のアクティビティーの投稿を表示する Web ページのソース・コード
Google+ のアクティビティーの投稿を表示する Web ページのソース・コード

アクティビティーのコンテンツと添付を取得する

リスト 1 ではアクティビティー・フィードのそのままのコードを示しましたが、フィードには動画や写真などの埋め込みリソースに関するメタデータなど、各投稿の追加情報が含まれています。それを念頭に置いた上でリスト 2 のコードを改修すると、これらの追加情報を抽出して表示することができます (リスト 3)。

リスト 3. Google+ のアクティビティー・フィードに含まれる追加データと埋め込みリソースを表示する
<!DOCTYPE html 
		 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
		 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Extracting data from a public activity feed</title>
    <style>
    table {
      border-collapse: yes;      
    }
    .photo {
      vertical-align: top;
    }
    td.divider {
      border-bottom: dashed silver 1px;
    }
    </style>
  </head>
		 <body>  
<?php
// load Zend classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Http_Client');

// define user ID
$uid = 'YOUR-ID-HERE';

// define API key
$key = 'YOUR-API-KEY-HERE';

try {
  // get feed of user public activities
  // decode JSON response
  $client = new Zend_Http_Client(
    "https://www.googleapis.com/plus/v1/people/$uid/activities/public?key=$key"
  );
  $response = $client->request('GET'); 
  $result = json_decode($response->getBody());

  // iterate through response  
  echo '<h1>' . $result->title . ' - ' . count($result->items) . 
    ' post(s) found</h1>';
  echo '<table>';
  foreach ($result->items as $entry) {
    echo '<tr>';
    echo '<td class="photo"><img src="' . $entry->actor->image->url . 
      '" /><br/>';  
    echo '<a href="' . $entry->actor->url . '">'. 
      $entry->actor->displayName . '</a></td><td>';
    if (!empty($entry->title)) {
      echo '<a href="' . $entry->url . '">' . $entry->title . 
        '</a> <br/>';
    }
    if (count($entry->object->attachments)) {
      foreach ($entry->object->attachments as $a) {
        switch ($a->objectType) {
          case 'article':
            echo '<a href="' . $a->url . '">Article: ' . 
              $a->displayName . '</a><br/>';
            break;
          case 'photo':
            echo '<a href="'.$a->fullImage->url.'"><img src="' . 
              $a->image->url . '" /> </a><br/>';
            break;
          case 'video':
            echo '<a href="' . $a->url . '">Video: ' . $a->displayName . 
              '</a><br/><img src="' . $a->image->url . 
              '" /><br/>';
            break;
        }
      }
    }
    echo 'Posted on ' . date("d M Y h:i", strtotime($entry->published));      
    echo '</td></tr><tr><td class=divider colspan=2>
      </td></tr>';
  }
  echo '</table>';  


  } catch (Exception $e) {
  echo 'ERROR:' . $e->getMessage();
}   
?>
  </body>
</html>

リスト 3リスト 2 をさらに一歩進め、各投稿の作成者の名前と写真を取得し、それらを投稿内容と共に表示しています。それ以外の埋め込み添付情報 (画像、動画、外部リンクなど) が含まれる投稿の場合には、各項目に含まれる attachments 配列に繰り返し処理を行い、その投稿に対応するリソースを投稿内容の下に表示します。図 5 は出力の一例です。

図 5. Google+ の投稿を添付情報と共に表示する Web ページ
Google+ の投稿を添付情報と共に表示する Web ページ

以下のリスト 4 は、ユーザーがアクティビティー ID を入力するとアクティビティーの詳細が表示されるようにすることで、リスト 3 よりもインタラクティブなバージョンにしています。リスト 4 は https://www.googleapis.com/plus/v1/activities/[ID] という別の API エンドポイントを使用しています。このエンドポイントにはアクティビティー ID を渡す必要があり、その結果として、そのアクティビティーの完全な詳細が 1 つの JSON レコードとして返されます。

リスト 4. Google+ のアクティビティー・フィードのコンテンツを表示するためのインタラクティブなフォーム
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Retrieving activity details</title>
    <style>
    table {
      border-collapse: yes;      
    }
    .photo {
      vertical-align: top;
    }
    td.divider {
      border-bottom: dashed silver 1px;
    }
    .meta {
      font-style: italic;
    }    
    </style>
  </head>
  <body>  
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Search for activity by ID: <input type="text" name="q" />
    <input type="submit" name="submit" value="Search">
    </form> 
    <?php
    if (isset($_POST['submit'])) {
      // load Zend classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define API key
      $key = 'YOUR-API-KEY-HERE';

      $aid = $_POST['q']; 
      
      try {
        // get user public feed
        // decode JSON response
        $client = new Zend_Http_Client(
          "https://www.googleapis.com/plus/v1/activities/$aid?key=$key"
        );
        $response = $client->request('GET'); 
        $entry = json_decode($response->getBody());
        
        // iterate through response  
        // print fields
        echo '<h1>' . $entry->title . '</h1>';
        echo '<table>';
        echo '<tr>';
        echo '<td class="photo"><img src="' . 
          $entry->actor->image->url . '" /></td><td>';  
        if (!empty($entry->title)) {
          echo '<a href="' . $entry->url . '">' . $entry->title . 
            '</a> <br/>';
        }
        if (count($entry->object->attachments)) {
          foreach ($entry->object->attachments as $a) {
            switch ($a->objectType) {
              case 'article':
                echo '<a href="' . $a->url . '">Article: ' . 
                  $a->displayName . '</a><br/>';
                break;
              case 'photo':
                echo '<a href="'.$a->fullImage->url.'"><img src="' . 
                  $a->image->url . '" /> </a><br/>';
                break;
              case 'video':
                echo '<a href="' . $a->url . '">Video: ' . 
                  $a->displayName . '</a><br/><img src="' . 
                  $a->image->url . '" /><br/>';
                break;
            }
          }
        }
        echo '<div class="meta">Posted on ' . 
          date("d M Y h:i", strtotime($entry->published)) . ' by <a href="' . 
          $entry->actor->url . '">'. $entry->actor->displayName . 
          '</a> <br/>';
        echo 'Replies: ' . (int)$entry->replies->totalItems . 
          ' | +1s: ' . (int)$entry->plusoners->totalItems . 
          ' | Reshares: ' . (int)$entry->resharers->totalItems . 
          '</div>';
        echo '</td></tr></table>';
        
      } catch (Exception $e) {
        echo 'ERROR:' . $e->getMessage();
      }   
    }
    ?>
  </body>
</html>

リスト 4 では、ユーザーがアクティビティー ID を入力するための入力フォームが追加されており、アクティビティー ID が入力されると Google+ API のエンドポイントに接続し、そのアクティビティーの完全なレコードを JSON 文書として取得しています。この JSON 文書はリスト 3 と同じような方法で PHP オブジェクトに変換され、フォーマット設定されて表示されます。リスト 4 では、各投稿に添付された追加のメタデータ (その投稿に対するコメントの数、共有の数、+1 の数など) を使用しています。そもそもアクティビティー ID をどのようにして取得するのかわからない人のために言うと、アクティビティー ID はアクティビティーの JSON 文書から抽出する必要があります。

図 6 はリスト 4 のフォームにアクティビティー ID を入力して得られた出力の一例です。

図 6. Google+ の投稿を添付情報と共に表示する Web ページ
Google+ の投稿を添付情報と共に表示する Web ページ

ユーザー・プロフィールを取得する

ユーザー・アクティビティー・リストを取得できるのと同じように、ユーザー・プロフィールを取得することができます。まず、対象のユーザーの Google ID を取得し、その ID を API エンドポイント https://www.googleapis.com/plus/v1/people/[ID] への呼び出しに含めます。その呼び出しに対する JSON レスポンスには、フルネーム、写真、略歴、URL など、ユーザーに関する情報が (入手可能なものであれば何でも) 含まれています。

このプロセスを説明したものがリスト 5 です。

リスト 5. Google+ のユーザー・プロフィールを取得するためのインタラクティブなフォーム
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Retrieving user profiles</title>
    <style>
    table {
      border-collapse: yes;      
    }
    .photo {
      vertical-align: top;
    }
    td.divider {
      border-bottom: dashed silver 1px;
    }
    </style>
  </head>
  <body>  
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Search for user by ID: <input type="text" name="q" />
    <input type="submit" name="submit" value="Search">
    </form> 
    
    <?php
    if (isset($_POST['submit'])) {
      // load Zend classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define API key
      $key = 'YOUR-API-KEY-HERE';
      
      $uid = $_POST['q'];

      try {
        // get user public feed
        // decode JSON response
        $client = new Zend_Http_Client(
          "https://www.googleapis.com/plus/v1/people/$uid?key=$key"
        );
        $response = $client->request('GET'); 
        $result = json_decode($response->getBody());
        
        // iterate through response  
        // print fields
        echo '<h1><img src="' . $result->image->url. '" />' . 
          $result->displayName . '</h1>';
        echo isset($result->tagline) ? '<h2>' . $result->tagline . 
          '</h1>' : '';
        echo isset($result->aboutMe) ? $result->aboutMe . '<br/>' : '';
        if (isset($result->urls) && count($result->urls)) {
        echo '<h3>Links</h3> <ul>';
        foreach ($result->urls as $u) {
          $label = '';
          if ($u->type == 'json') continue;
          if ($u->type == 'profile') $label = 'Google+ Profile: ';
          echo '<li><a href="'. $u->value . '">' . $label . 
            $u->value . '</a></li>';
        }
        echo '</ul>';
        }  
          
      } catch (Exception $e) {
        echo 'ERROR:' . $e->getMessage();
      }   
    }
    ?>
  </body>
</html>

リスト 5リスト 4 と似ており、ユーザーの Google ID を要求した後に API に接続し、そのユーザーに関する情報を取得しています。レスポンスには通常、少なくとも、ユーザーの名前と、写真の URL (ユーザーの写真がない場合はデフォルトの写真) が含まれています。ユーザーが自分自身に関する追加データを入力してある場合には、その情報も JSON レスポンスに含まれます。先ほどと同様、このレスポンスを PHP オブジェクトに変換し、フォーマットを設定してブラウザーに表示することができます。

図 7リスト 5 のフォームにアクティビティー ID を入力して得られた出力の一例です。

図 7. Google+ のユーザー・プロフィールを表示する Web ページ
Google+ のユーザー・プロフィールを表示する Web ページ

アクティビティー・ストリームを検索する

1 つの一般公開フィードまたはユーザー・プロフィールを取得する他にも、Google+ API とキーワードを使用してアクティビティー・フィードを検索することもできます。この API メソッドはエンドポイント https://www.googleapis.com/plus/v1/activities で利用することができ、検索対象の 1 つ以上のキーワードを含む query パラメーターを受け付けます。リスト 6 は、この API を PHP アプリケーションで使用する場合を示しています。

リスト 6. キーワードを使用してアクティビティーを検索する
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Searching public activity feeds</title>
    <style>
    table {
      border-collapse: yes;      
    }
    .photo {
      vertical-align: top;
    }
    td.divider {
      border-bottom: dashed silver 1px;
    }
    </style>
  </head>
  <body>  
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Search for: <input type="text" name="q" />
    <input type="submit" name="submit" value="Search">
    </form>    
    <?php
    
    if (isset($_POST['submit'])) {
      // load Zend classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define API key
      $key = 'YOUR-API-KEY-HERE';
      
      try {
        if (empty($_POST['q'])) {
          throw new Exception('No search term provided');  
        }
        
        // search all feeds
        $url = "https://www.googleapis.com/plus/v1/activities?key=$key&query=" . 
          urlencode($_POST['q']);
        $client = new Zend_Http_Client($url);
        $response = $client->request('GET'); 
        $result = json_decode($response->getBody());

        // iterate through returned feed  
        // display results
        echo '<h1>' . $result->title . ' - ' . 
          count($result->items) . ' post(s) found</h1>';
        echo '<table>';
        foreach ($result->items as $entry) {
          echo '<tr>';
          echo '<td class="photo"><img src="' . 
            $entry->actor->image->url . '" /><br/>';  
          echo '<a href="' . $entry->actor->url . '">'. 
            $entry->actor->displayName . '</a></td><td>';
          if (!empty($entry->title)) {
            echo '<a href="' . $entry->url . '">' . $entry->title . 
              '</a> <br/>';
          }
          if (count($entry->object->attachments)) {
            foreach ($entry->object->attachments as $a) {
              switch ($a->objectType) {
                case 'article':
                  echo '<a href="' . $a->url . '">Article: ' . 
                    $a->displayName . '</a><br/>';
                  break;
                case 'photo':
                  echo '<a href="'.$a->fullImage->url.'"><img src="' . 
                    $a->image->url . '" /> </a><br/>';
                  break;
                case 'video':
                  echo '<a href="' . $a->url . '">Video: ' . $a->displayName . 
                    '</a><br/><img src="' . $a->image->url . 
                    '" /><br/>';
                  break;
              }
            }
          }
          echo 'Posted on ' . date("d M Y h:i", strtotime($entry->published));      
          echo '</td></tr><tr>
            <td class=divider colspan=2></td></tr>';
        }
        echo '</table>';  
      } catch (Exception $e) {
        echo 'ERROR:' . $e->getMessage();
      }              
    }
    ?>
  </body>
</html>

リスト 6 によって、ユーザーが 1 つ以上のキーワードを入力するための入力フィールドを含む Web フォームが生成されます。このフォームが送信されると、新しい Zend_Http_Client インスタンスが作成され、ユーザーが入力した内容は API エンドポイントに対する GET リクエストに含められます。返される JSON レスポンスは PHP オブジェクトに変換されて処理されます。

図 8リスト 6 のフォームにキーワードを入力して得られた出力の一例です。

図 8. Google+ のアクティビティーをキーワードで検索するための Web フォーム
Google+ のアクティビティーをキーワードで検索するための Web フォーム

デフォルトで、Google+ API によって返される各結果セットには 10 項目が含まれています。返される結果の数を変更するには、API リクエストに maxResults パラメーターを追加し、1 から 20 の間の値を指定します。API によって返される各 JSON 文書には、nextPageToken プロパティーも含まれています。このプロパティーをクエリー・ストリングに追加すると、次のページの結果セットを取得することができ、データ・セットをページ分けすることができます。


ユーザー・プロフィールを検索する

Google+ API を使用するとキーワードで人々を検索することができます。そのための API エンドポイントは https://www.googleapis.com/plus/v1/people です。アクティビティーを検索するための API の場合と同様、この API エンドポイントはキーワードを含む query パラメーターを受け付け、そのパラメーターの中にあるキーワードを検索します。

リスト 7 はアクティビティーの代わりに人を検索するようにリスト 6 を変更しています。

リスト 7. ユーザー・プロフィールによってアクティビティーを検索する
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Searching for people</title>
    <style>
    table {
      border-collapse: yes;      
      width: 100%;
    }
    .photo {
      vertical-align: top;
    }
    .posts td:not(:last-child) {
      border-bottom: dashed silver 1px;
    }
    td.divider {
      border-bottom: solid green 2px;    
    }
    td.post {
      padding-bottom: 20px;
    }
    .meta {
      font-style: italic;
    }
    </style>     
  </head>
  <body>  
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Search for people by name: <input type="text" name="q" />
    <input type="submit" name="submit" value="Search">
    </form>    
    <?php
    
    if (isset($_POST['submit'])) {
      // load Zend classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define API key
      $key = 'YOUR-API-KEY-HERE';
      
      try {
        if (empty($_POST['q'])) {
          throw new Exception('No search term provided');  
        }
        
        // search all feeds
        $url = "https://www.googleapis.com/plus/v1/people?key=$key&query=" . 
          urlencode($_POST['q']);
        $client = new Zend_Http_Client($url);
        $response = $client->request('GET'); 
        $result = json_decode($response->getBody());

        // iterate through returned feed  
        // display results
        echo '<h1>' . $result->title . ' - ' . count($result->items) . 
          ' user(s) found</h1>';
        echo '<table>';
        foreach ($result->items as $entry) {
          echo '<tr>';
          echo '<td class="photo"><img src="' . $entry->image->url . 
            '" /><br/>';  
          echo '<a href="' . $entry->url . '">'. $entry->displayName . 
            '</a></td><td>';
          
          // get user's three most recent public posts
          $client->setUri("https://www.googleapis.com/plus/v1/people/" . 
            $entry->id . "/activities/public?key=$key&maxResults=3");
          $response = $client->request('GET'); 
          $result2 = json_decode($response->getBody()); 
          echo '<table class="posts">';
          foreach ($result2->items as $entry2) {
            echo '<tr><td class="post">';
            if (!empty($entry2->title)) {
              echo '<a href="' . $entry2->url . '">' . 
                $entry2->title . '</a> <br/>';
            }
            if (count($entry2->object->attachments)) {
              foreach ($entry2->object->attachments as $a) {
                switch ($a->objectType) {
                  case 'article':
                    echo '<a href="' . $a->url . '">Article: ' . 
                      $a->displayName . '</a><br/>';
                    break;
                  case 'photo':
                    echo '<a href="'.$a->fullImage->url.'"><img src="' . 
                      $a->image->url . '" /> </a><br/>';
                    break;
                  case 'video':
                    echo '<a href="' . $a->url . '">Video: ' . 
                      $a->displayName . '</a><br/><img src="' . 
                      $a->image->url . '" /><br/>';
                    break;
                }
              }
            }
            echo '<span class="meta">Posted on ' . 
              date("d M Y h:i", strtotime($entry2->published)) . '</span>';      
            echo '</td></tr>';
          }
          echo '</table>';
          echo '</td></tr><tr>
            <td class=divider colspan=2></td></tr>';
        }
        echo '</table>';
      } catch (Exception $e) {
        echo 'ERROR:' . $e->getMessage();
      }              
    }
    ?>
  </body>
</html>

リスト 7 で興味深い点は、2 つの API メソッド呼び出しを使用していることです。最初に API エンドポイント https://www.googleapis.com/plus/v1/people に対して、指定されたキーワードと一致するユーザー・プロフィールを照会しています。そして取得したプロフィールの集合に対して繰り返し処理を行い、指定キーワードに一致する各プロフィールからユーザーの Google ID を取得し、そのユーザー ID を API エンドポイント https://www.googleapis.com/plus/v1/people/[ID]/activities/public に対する第 2 のリクエストに埋め込み、そのユーザーの最新の投稿を 3 つ取得しています。リスト 6 の場合と同じように、各投稿には、関連する埋め込みリソース (画像、動画、外部の記事など) へのリンクが付けられています。

リスト 7 を実行すると、結果は図 9 のようになります。

図 9. Google+ のユーザー・プロフィールをキーワードで検索するための Web フォーム
Google+ のユーザー・プロフィールをキーワードで検索するための Web フォーム

アクティビティーに対するコメントを取得する

Google+ では、ユーザーがメッセージや写真、動画、リンクを含むアクティビティーを投稿することができ、これらのアクティビティーに他のユーザーがコメントすることもできます。コメントの内容を取得するためには、API エンドポイント https://www.googleapis.com/plus/v1/activities/[ID]/comments にアクセスすることで各アクティビティーのコメント・フィードを利用します。先ほど紹介したコードを元に作成されたリスト 8 を見ると、アクティビティーとそのコメントの表示方法がわかるはずです。

リスト 8. アクティビティーのコメントを表示する
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Retrieving comments</title>
    <style>
    table {
      border-collapse: yes;      
    }
    .photo {
      vertical-align: top;
    }
    td.divider {
      border-bottom: dashed silver 1px;
    }
    .meta {
      font-style: italic;
    }
    </style>
  </head>
  <body>  
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Search for comments on activity (enter activity ID): 
      <input type="text" name="q" />
    <input type="submit" name="submit" value="Search">
    </form> 
    <?php
    if (isset($_POST['submit'])) {
      // load Zend classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define API key
      $key = 'YOUR-API-KEY-HERE ';

      $aid = $_POST['q']; 
      
      try {
        // get activity feed
        // decode JSON response
        $client = new Zend_Http_Client(
          "https://www.googleapis.com/plus/v1/activities/$aid?key=$key"
        );
        $response = $client->request('GET'); 
        $entry = json_decode($response->getBody());
        
        // iterate through response  
        // print fields
        echo '<h1>' . $entry->title . '</h1>';
        echo '<table>';
        echo '<tr>';
        echo '<td class="photo"><img src="' . 
          $entry->actor->image->url . '" /></td><td>';  
        if (!empty($entry->title)) {
          echo '<a href="' . $entry->url . '">' . $entry->title . 
            '</a> <br/>';
        }
        if (count($entry->object->attachments)) {
          foreach ($entry->object->attachments as $a) {
            switch ($a->objectType) {
              case 'article':
                echo '<a href="' . $a->url . '">Article: ' . 
                  $a->displayName . '</a><br/>';
                break;
              case 'photo':
                echo '<a href="'.$a->fullImage->url.'"><img src="' . 
                  $a->image->url . '" /> </a><br/>';
                break;
              case 'video':
                echo '<a href="' . $a->url . '">Video: ' . $a->displayName . 
                  '</a><br/><img src="' . $a->image->url . '" /><br/>';
                break;
            }
          }
        }
        echo '<div class="meta">Posted on ' . 
          date("d M Y h:i", strtotime($entry->published)) . ' by <a href="' . 
          $entry->actor->url . '">'. $entry->actor->displayName . 
          '</a> <br/>';
        echo 'Replies: ' . (int)$entry->replies->totalItems . 
          ' | +1s: ' . (int)$entry->plusoners->totalItems . 
          ' | Reshares: ' . (int)$entry->resharers->totalItems . 
          '</div>';
        echo '</td></tr></table>';
        
        // get comments feed for activity
        $client->setUri(
          "https://www.googleapis.com/plus/v1/activities/$aid/comments?key=$key"
        );
        $response = $client->request('GET'); 
        $result = json_decode($response->getBody());
        
        // iterate through response  
        // print fields
        if (count($result->items)) {
          echo '<h3>' . $result->title . '</h3>';
          echo '<ul>';
          foreach ($result->items as $comment) {        
            echo '<li>' . $comment->object->content . 
              '<br/>';
            echo '<span class="meta">Posted on ' . 
              date("d M Y h:i", strtotime($comment->published)) . 
              ' by <a href="' . $comment->actor->url . '">'. 
              $comment->actor->displayName . '</a> </span>';
            echo '</li>';
          }
          echo '</ul>';
        }

      } catch (Exception $e) {
        echo 'ERROR:' . $e->getMessage();
      }   
    }
    ?>
  </body>
</html>

リスト 8 の最初の部分はリスト 4 に似ています。この部分では、ユーザーが Web フォームに入力したアクティビティー ID を受け付けて API に接続し、そのアクティビティーの詳細を取得して表示します。次にこのスクリプトはアクティビティーのコメント・フィードに対して第 2 の API 呼び出しを実行し、その結果として、そのアクティビティーに対して他のユーザーが投稿したコメントすべてを含む JSON 文書が返されます。この JSON 文書は構文解析され、各コメントの内容が公開時刻と投稿者の名前と共に Web ページに追加されます。

図 10 はリスト 8 のフォームにアクティビティー ID を入力して得られた出力の一例です。

図 10. Google+ のアクティビティーとコメントを表示する Web ページ
Google+ のアクティビティーとコメントを表示する Web ページ

まとめ

Google+ API はまだ比較的歴史が浅く、この記事の執筆時点では読み取り操作しかサポートしていません。しかしこの記事の例で学んだように、Google+ API には一般公開されている Google+ のコンテンツを任意の Web アプリケーションに統合するためのオプションがいくつも用意されています。Google+ サービスの範囲が広がるにつれて Google+ API が成熟し、さらに多くの機能が提供されるようになることを期待しましょう。それまで Google+ API は、マッシュアップを作成したり、Google+ に対するカスタム・インターフェースを作成したりするための素晴らしいツールとして使用することができます。Google+ API を利用したコーディングを楽しんでください!

参考文献

学ぶために

  • Google+ API: この API を使用してアプリケーションや Web サイトに Google+ のコンテンツを統合する方法について学んでください。
  • Google アカウント: 無料のアカウントを作成してください。
  • Google APIs Console: API キーとトークンを作成してください。
  • Paul Fang 氏のブログ記事: Google+ のユーザーが 6,200 万人を超え、毎日 625,000 人の新しいユーザーが加わっているという記事を読んでください。
  • 利用規約開発者ポリシー: Google+ API についての情報を検討してみてください。
  • Zend_Http_Client コンポーネント: このコンポーネントがサポートする機能についての資料を読んでください。このコンポーネントは HTTP クライアントに期待される最も単純な機能だけではなく、HTTP 認証やファイルのアップロードなどの複雑な機能もサポートしています。
  • 著者の Vikram Vaswani が developerWorks に寄稿した他の記事 (2007年8月から現在まで): XML、他の Google API、その他の技術に関する記事を読んでください。
  • New to XML には、XML を学ぶために必要なリソースが豊富に用意されています。
  • developerWorks の XML ゾーン: DTD、スキーマ、XSLT など、XML の領域でのスキルを磨くためのリソースが豊富に用意されています。XML の技術文書一覧には、広範な話題を網羅した技術記事やヒント、チュートリアル、技術標準、IBM Redbooks が豊富に用意されています。
  • IBM XML certification: XML および関連技術において IBM 認定技術者になる方法を参照してください。
  • developerWorks の Technical events and webcasts: これらのセッションで最新情報を入手してください。
  • developerWorks on Twitter: 今すぐ Twitter に参加して developerWorks のツイートをフォローしてください。
  • developerWorks podcasts: ソフトウェア開発者のための興味深いインタビューや議論を聞いてください。
  • developerWorks on-demand demos: 初心者のための製品インストール方法やセットアップのデモから、上級開発者のための高度な機能に至るまで、多様な話題が解説されています。

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

  • Zend Framework をダウンロードしてください。
  • 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=829166
ArticleTitle=Google+ のアクティビティー・ストリームを検索し、PHP アプリケーションと統合する
publish-date=08092012