目次


Picasa Web Albums を使って PHP アプリケーションを作成する

カスタムの PHP アプリケーションの中に Picasa Web Albums のデータを統合する

Comments

はじめに

デジタル写真を大量に撮る人の例に漏れず、私のディスクも整理されていません。私のコンピューターには古い写真が何百メガバイトも保存されており、その大部分は簡単なラベルが付いているだけであったり、まったくラベルが付いていなかったりします。ほんの数ヶ月前、ついに私は Google による無料の Picasa 写真管理ソフトウェアを初めて試したのですが、膨大なデータを整理する中から、ある手法を利用するとよいことがわかってきました。

Picasa は Web からダウンロードできるツールであるだけでなく、Picasa Web Albums という写真共有用の無料サイトとしてオンラインでも存在しています。この Web サイトでユーザーができることは、写真やビデオをアップロードし、それらをアルバムに分類し、容易に検索できるようにキーワードでタグ付けし、そして他の人達と共有することです。しかし最も魅力的なのは、Google が提供する多くのツールと同様、表面的な機能ではなく Picasa Web Albums が公開している Data API です。この Data API を利用すると、ユーザーのフォト・アルバムの中に保存された画像を扱うカスタム・アプリケーションを作成することができます。この、REST モデルに従う API にアクセスするためには、XML 機能を持った開発ツールキットを使います。この API には多くの一般的なプログラミング言語のためのクライアント・ライブラリーが既に用意されており、そうした言語の中には、私が最も頻繁に使用する言語である PHP も含まれています。

この記事では Google Picasa Web Albums Data API を紹介し、また Picasa のアルバムや写真を PHP アプリケーションと統合して使用するための方法を説明します。ここで紹介する例には、アルバムや写真を取得する方法や、カスタマイズした Web インターフェースを使って写真をアップロードする方法、そしてキーワードによって写真を検索する方法などが含まれています。では早速始めることにしましょう。

Picasa Web Albums Data API を理解する

PHP コードの詳細に入る前に、Picasa Web Albums Data API について少し説明しておきましょう。REST ベースのすべてのサービスの場合と同じく、すべては指定されたリソースへの HTTP リクエストで始まります。この HTTP リクエストには 1 つ以上の入力パラメーターを持つクエリーが含まれており、サーバーはこのクエリーに対して、XML 対応のクライアントで構文解析するのに適した Atom または RSS フォーマットのレスポンス (つまりフィード) で応答します。

典型的な Picasa フィードには大量の情報が含まれています。その一例を見るためには、Web ブラウザーで http://picasaweb.google.com/data/feed/api/user/userid?kind=photo という URL の内容を表示してみます (userid の部分を皆さんの Google アカウントのユーザー名で置き換える必要があります)。何らかの写真やアルバムを既に Picasa Web Albums に保存してあるとすると、リスト 1 のようなものが表示されるはずです。

このリスト 1 の内容を簡単に調べ、このフィードの主な要素に慣れることにしましょう。

  • Picasa Web Albums Data API はリクエストされたデータを含むフィードによって REST リクエストに応答します。フィードにはさまざまな種類があります (アルバム・フィード、フォト・フィード、ユーザー・フィード、ユーザー連絡先フィード、など)。従ってほとんどの場合、XML レスポンスには <feed> 要素がルート要素として含まれています。<feed> 要素には <link> 要素と <openSearch:> 要素が含まれており、さらに <link> 要素には結果セットの現在のページの URL と次のページの URL、そして前のページの URL が、そして <openSearch:> 要素には検索に対する統計の要約が含まれています。
  • 最も外側にある <feed> 要素には 1 つ以上の <entry> 要素が含まれており、それぞれの <entry> 要素はそのクエリーに一致する 1 枚の写真を表しています。各 <entry> には、その写真に関するさらなる情報 (写真の説明、ファイル名、公開日、作成者など) とその写真の表示と編集のための URL リンクを示す <link> 要素も含まれています。
  • 各 <entry> の中にある一連の <gphoto:> 要素には、その写真に関する詳細情報が含まれています (写真のファイル・サイズや寸法、アルバム、コメント数など)。
  • 各 <entry> の中にある <media:group> 要素には、写真のキーワードと、サムネイル・リンクが含まれています。

SimpleXML を使って写真を取得する

では、PHP と SimpleXML を使って Picasa Web Albums のフィードを解析する簡単な例に進みましょう。リスト 2リスト 1 のフィードを取得し、SimpleXML を使ってそのフィードから関連するデータ・フラグメントを抽出し、そしてそのデータ・フラグメントを Web ページのフォーマットにします。

リスト 2: SimpleXML を使って写真の一覧を取得する
<!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>Listing album contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    img {
      float: left;  
    }
    </style>    
  </head>
  <body>
    <?php
    $userid = 'userid%40googlemail.com';

    // build feed URL
    $feedURL = "http://picasaweb.google.com/data/feed/api/user/$userid?kind=photo";
    
    // read feed into SimpleXML object
    $sxml = simplexml_load_file($feedURL);
    
    // get album name and number of photos
    $counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    $total = $counts->totalResults; 
    ?>
    <h1><?php echo $sxml->title; ?></h1>
    <?php echo $total; ?> photo(s) found.
    <p/>

    <?php    
    // iterate over entries in album
    // print each entry's title, size, dimensions, tags, and thumbnail image
    foreach ($sxml->entry as $entry) {
      $title = $entry->title;
      $summary = $entry->summary;
      
      $gphoto = $entry->children('http://schemas.google.com/photos/2007');
      $size = $gphoto->size;
      $height = $gphoto->height;
      $width = $gphoto->width;
      
      $media = $entry->children('http://search.yahoo.com/mrss/');
      $thumbnail = $media->group->thumbnail[1];
      $tags = $media->group->keywords;
      
      echo "<h2>$summary</h2>\n";
      echo "<table><tr><td><img src=\"" . 
      $thumbnail->attributes()->{'url'} . "\"/></td>\n";
      echo "<td><span class=\"attr\">File</span>: $title 
      <br />\n";
      echo "<span class=\"attr\">Size</span>: $size bytes 
      ($height x $width) <br />\n";
      echo "<span class=\"attr\">Tags</span>: $tags 
      </td></tr></table>\n";
    }
    ?>
    
  </body>
</html>

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

図 1. 写真の一覧を表示する Web ページ
写真の一覧を表示する Web ページ
写真の一覧を表示する Web ページ

リスト 2 では、まず simplexml_load_file() オブジェクトを使ってフィード URL にリクエストを送信し、そのレスポンスを SimpleXML オブジェクトに変換します。次にレスポンスの中にある各 <entry> 要素を foreach() ループにより繰り返し処理し、図 1 に示す情報を取得します。各 <entry> の下にある子要素は SimpleXML のオブジェクト・プロパティーとして表現されます。例えば <title> ノードは $entry->title によって表現され、<summary> ノードは $entry->summary によって表現されるといった具合です。キーワードとサムネイル画像は各 <entry> の下にある <media:group> から取得されます。

ユーザー・フィードとアルバム・フィードを処理する

ある特定のユーザーが作成したすべてのアルバムの一覧を取得したい場合も、処理は簡単です。この場合はリスト 2 のフィード URL を使いますが、写真ではなくアルバムを一覧表示するために kind パラメーターを変更します。リスト 3 は、そうしたフィードを取得し、解析するための方法を示しています。

リスト 3: SimpleXML を使ってアルバムの一覧を取得する
<!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>Listing albums</title>
    <style>
    body {
      font-family: Verdana;      
    }
    </style>    
  </head>
  <body>
    <h1>Album Listing</h2>
    <?php
    $userid = 'userid%40googlemail.com';
    
    // build feed URL
    $feedURL = "http://picasaweb.google.com/data/feed/api/user/$userid?kind=album";
    
    // read feed into SimpleXML object
    $sxml = simplexml_load_file($feedURL);
    
    // get album names and number of photos in each
    echo "<ul>";
    foreach ($sxml->entry as $entry) {      
      $title = $entry->title;
      $gphoto = $entry->children('http://schemas.google.com/photos/2007');
      $numphotos = $gphoto->numphotos;      
      echo "<li>$title - $numphotos photo(s)</li>\n";
    }
    echo "</ul>";
    ?>
    
  </body>
</html>

図 2 は、この変更を行った出力の例を示しています。

図 2. アルバムの一覧を表示する Web ページ
アルバムの一覧を表示する Web ページ
アルバムの一覧を表示する Web ページ

ある特定のアルバムの写真のみを一覧表示するアルバム・フィードを取得するには、フィード URL の中でアルバムの名前を指定します。リスト 4 はそうしたフィードを取得し、解析するための方法を示しています。

リスト 4: SimpleXML を使ってアルバムの中の写真を取得する
<!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>Listing album contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    img {
      float: left;  
    }
    </style>    
  </head>
  <body>
    <?php
    $userid = 'userid%40googlemail.com';
    $album = 'France2008';
    
    // build feed URL
    $feedURL = "http://picasaweb.google.com/data/feed/api/user/$userid/album/$album";
    
    // read feed into SimpleXML object
    $sxml = simplexml_load_file($feedURL);
    
    // get album name and number of photos
    $counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    $total = $counts->totalResults; 
    ?>
    <h1><?php echo $sxml->title; ?></h1>
    <?php echo $total; ?> photo(s) found.
    <p/>

    <?php    
    // iterate over entries in album
    // print each entry's title, size, dimensions, tags, and thumbnail image
    foreach ($sxml->entry as $entry) {
      $title = $entry->title;
      $summary = $entry->summary;
      
      $gphoto = $entry->children('http://schemas.google.com/photos/2007');
      $size = $gphoto->size;
      $height = $gphoto->height;
      $width = $gphoto->width;
      
      $media = $entry->children('http://search.yahoo.com/mrss/');
      $thumbnail = $media->group->thumbnail[1];
      $tags = $media->group->keywords;
      
      echo "<h2>$summary</h2>\n";
      echo "<table><tr><td><img src=\"" . 
      $thumbnail->attributes()->{'url'} . "\"/></td>\n";
      echo "<td><span class=\"attr\">File</span>: $title 
      <br />\n";
      echo "<span class=\"attr\">Size</span>: $size bytes 
      ($height x $width) <br />\n";
      echo "<span class=\"attr\">Tags</span>: $tags 
      </td></tr></table>\n";
    }
    ?>
    
  </body>
</html>

そして図 3 はその出力の例を示しています。

図 3. アルバムの写真の一覧を表示する Web ページ
アルバムの写真の一覧を表示する Web ページ
アルバムの写真の一覧を表示する Web ページ

Zend GData Client Library を使って写真を取得する

ここまでの例では、PHP を使って Picasa Web Albums からデータを読み取り、そのデータを使用することがいかに容易であるかを示しました。しかし読み取り専用アクセスには限界があります。書き込みアクセスが必要な、もっと高度な操作 (新しい写真やアルバムの追加など) を実現するためには、Google が承認した 2 つの認証方法である AuthSub または ClientLogin のうちの 1 つを使って、アプリケーションにユーザー認証を追加する必要があります。

このタイプの認証を手動で行おうとすると非常に面倒であり、また典型的な認証トランザクションの間に発生する可能性のあるさまざまなシナリオに対応するために、大量のコードが必要です。幸いなことに、この点に関してあまり心配する必要はありません。PHP アプリケーションを Google Data API と統合するために専用に設計された Zend の GData Client Library が、すべての詳細を処理してくれるのです。この別途ダウンロード (「参考文献」にリンクがあります) できるライブラリーは、Google Data API に対する便利なオブジェクト指向のインターフェースを提供し、(認証を含めて) 一般的なタスクの大部分をカプセル化しているため、開発者はそうした部分を作成する作業から解放され、アプリケーションのコア機能に集中することができます。

リスト 5 は Zend GData Client Library を使ってリスト 4 の機能を再現したものです。

リスト 5: Zend GData Client Library を使ってアルバムの写真を取得する
<!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>Listing album contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    img {
      float: left;  
    }
    </style>    
  </head>
  <body>
    <?php
    // load library
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Gdata_Photos');
    Zend_Loader::loadClass('Zend_Http_Client');
    
    // create authenticated HTTP client for Picasa service
    $svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
    $user = "userid@gmail.com";
    $pass = "secret";
    $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
    $gphoto = new Zend_Gdata_Photos($client);
    
    // generate query to get album feed
    $query = $gphoto->newAlbumQuery();    
    $query->setUser("default");
    $query->setAlbumName("France2008");
    
    // get and parse album feed
    // get album name and number of photos
    try {
      $feed = $gphoto->getAlbumFeed($query);
    } catch (Zend_Gdata_App_Exception $e) {
      echo "Error: " . $e->getResponse();
    }
    ?>
    <h1><?php echo $feed->getTitle(); ?></h1>
    <?php echo $feed->getTotalResults(); ?> photo(s) found.
    <p/>

    <?php        
    // process each photo entry
    // print each entry's title, size, dimensions, tags, and thumbnail image
    foreach ($feed as $entry) {
      $title = $entry->getTitle();
      $summary = $entry->getSummary();
      $thumbnail = $entry->getMediaGroup()->getThumbnail();
      $tags = $entry->getMediaGroup()->getKeywords();
      $size = $entry->getGphotoSize();
      $height = $entry->getGphotoHeight();
      $width = $entry->getGphotoWidth();
      
      echo "<h2>$summary</h2>\n";
      echo "<table><tr><td><img src=\"" . 
      $thumbnail[1]->url . "\"/></td>\n";
      echo "<td><span class=\"attr\">File</span>: $title 
      <br />\n";
      echo "<span class=\"attr\">Size</span>: $size bytes 
      ($height x $width) <br />\n";
      echo "<span class=\"attr\">Tags</span>: $tags 
      </td></tr></table>\n";
    }
    ?>

  </body>
</html>

リスト 5 はまず Zend のクラス・ライブラリーをロードし、それから Zend_Http_Client クラスのインスタンスを初期化しています。このクライアントはユーザーの認証に必要な情報を持っており、Picasa サービスへの認証接続を開きます。認証接続が開かれたら、getAlbumFeed() メソッドを使ってアルバムのフィードを取得します。このメソッドは、次の 2 つのパラメーターで構成される AlbumQuery オブジェクトを受け付けます。

  • 所有者の Picasa ユーザー名
  • アルバム名

getAlbumFeed() API による呼び出しに対するレスポンスは、リスト 1 に似た XML フィードであり、この XML フィードは解析されて PHP オブジェクトに変換されます。この PHP オブジェクトは、ゲッターとセッターというマジック・メソッドを公開することで、オブジェクトやプロパティーによる表記によって XML フィードの中のノードから特定の情報部分を容易に取得することができるようにします。従って、例えば getSummary() メソッドを使うと写真の要約を取得することができ、また getGphotoSize() メソッドを使うと写真ファイルのバイト・サイズを取得することができます。

図 4 は出力の一例を示しています。

図 4. アルバムの写真を一覧表示した Web ページ
アルバムの写真を一覧表示した Web ページ
アルバムの写真を一覧表示した Web ページ

新しい写真を追加する

これで写真を一覧表示できるようになったので、今度は新しい写真を追加してはどうでしょう。これは実際、思ったほど複雑ではありません。

新しい写真を追加するには、単純にその画像ファイルを関連のメタデータと共に (MIME エンコードしたブロックとして) アルバム・フィードの URL に POST します。そのブロックの 1 つの部分には XML にエンコードした <entry> を含む必要があり、他の部分にはバイナリー・データを含む必要があります。リスト 6 はそうしたブロックの一例です。

リスト 6. 新しい写真をメタデータと共に追加するための POST パケットの例
--=_00fb9c5957c74e05312cbc2f9d1d09b8
Content-Type: application/atom+xml
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
  <atom:category term="http://schemas.google.com/photos/2007#photo" 
  scheme="http://schemas.google.com/g/2005#kind"/>
  <atom:summary type="text">Notre Dame, Paris</atom:summary>
  <media:group xmlns:media="http://search.yahoo.com/mrss/">
    <media:keywords>church, paris</media:keywords>
  </media:group>
</atom:entry>

--=_00fb9c5957c74e05312cbc2f9d1d09b8
Content-Type: image/jpeg

[binary data]

Zend ライブラリーを使用すると、作業はもっと簡単になります。insertPhotoEntry() メソッドを呼び出すだけで、このメソッドがリスト 6 の POST パケットを作成し、そしてそのパケットをアルバム・フィードに POST してくれます。リスト 7 は、ユーザーに写真のファイルとタイトル、そしてタグを要求する Web フォームを作成する方法と、Zend ライブラリーを使って対応する POST パケットを作成し、写真のデータをアルバムに追加する方法を示しています。

リスト 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>Adding photos to an album</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <h1>Add Photo</h1>
    <?php if (!isset($_POST['submit'])) { ?>
    <form method="post" action="<?php 
     echo htmlentities($_SERVER['PHP_SELF']); ?>" enctype="multipart/form-data">
      Title: <br/>
      <input name="title" type="text" size="25" /><p/>
      File to upload: <br/>
      <input name="photofile" type="file" /><p/>      
      Tags: <br/>
      <input name="tags" type="text" size="25" /><p/>
      <input name="submit" type="submit" value="Save" />
    </form>
    <?php
    } else {
      // load classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Gdata');
      Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
      Zend_Loader::loadClass('Zend_Gdata_Photos');
      Zend_Loader::loadClass('Zend_Http_Client');
      
      // connect to service
      $svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
      $user = "userid@gmail.com";
      $pass = "secret";
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
      $gphoto = new Zend_Gdata_Photos($client);
      
      // validate input
      if (empty($_POST['title'])) {
        die('ERROR: Missing title');
      } 
      
      // sanitize input
      $title = htmlentities($_POST['title']);
      $tags = htmlentities($_POST['tags']);

      // set album name
      $albumName = "France2008";

      // construct photo object
      // save to server      
      try {        
        $photo = $gphoto->newPhotoEntry();
        
        // set file
        $file = $gphoto->newMediaFileSource($_FILES['photofile']['tmp_name']);
        $file->setContentType("image/jpeg");
        $photo->setMediaSource($file);
        
        // set title
        $photo->setSummary($gphoto->newSummary($title));
        
        // set tags
        $photo->mediaGroup = new Zend_Gdata_Media_Extension_MediaGroup();
        $keywords = new Zend_Gdata_Media_Extension_MediaKeywords();
        $keywords->setText($tags);
        $photo->mediaGroup->keywords = $keywords;
        
        // link to album
        $album = $gphoto->newAlbumQuery();        
        $album->setUser($user);
        $album->setAlbumName($albumName);
        
        // save photo
        $gphoto->insertPhotoEntry($photo, $album->getQueryUrl()); 
      } catch (Zend_Gdata_App_Exception $e) {
        echo "Error: " . $e->getResponse();
      }
      echo 'Photo successfully added!';      
    }
    ?>
  </body>
</html>

リスト 7 は実際には次の 2 つの部分から構成されています。

  • Web フォーム
  • フォームをとおして送信された入力を処理する PHP コード

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

図 5. 新しい写真を追加するための Web フォーム
新しい写真を追加するための Web フォーム
新しい写真を追加するための Web フォーム

ユーザーが、アップロードする画像ファイル (File to upload) を選択し、タイトル (Title) とオプションのタグ (Tag) を入力してフォームを送信すると、このスクリプトの後半にアクションが移ります。後半ではまず、HTTP クライアントが初期化され、この HTTP クライアントが Picasa Web Albums Data API への認証接続を開きます。そして、Web フォームに入力された内容が検証されると、新しい PhotoEntry() オブジェクトが初期化され、このオブジェクトに新しい写真用のデータが保存されます。

次に、フォームに入力されたキーワードとタイトルがこのオブジェクトに追加されます (それぞれに対して、このオブジェクトの mediaGroup プロパティーと setSummary() メソッドが使われます)。PHP によるファイル・アップロード用の特別な配列 ($_FILES) はアップロードされたファイルの名前を取得します。そして setMediaSource() メソッドがこのファイルをこのオブジェクトに追加します。最後に、setAlbumName() メソッドがその写真のリンク先となるアルバムを指定します (アルバムの値をデフォルトに設定し、画像をデフォルトのアルバム (つまりドロップ・ボックス) に配置します)。

こうしたさまざまなオブジェクト・パラメーターを構成できると、insertPhotoEntry() メソッドが実際に写真とメタデータを Google のサーバーに保存します。写真が追加されると、その写真は、対応するアルバムに即座に表示されるはずです。

図 6 は新しい写真が適切に追加された後の出力を示しています。

図 6. 新しい写真を追加した結果
新しい写真を追加した結果
新しい写真を追加した結果

写真の削除と変更

写真を削除するためには、その写真固有の URL に DELETE リクエストを送信します。Zend ライブラリーの場合で言えば、写真の ID とアルバムの ID を使って写真の URL を作成し、(オブジェクトとしての) その写真への参照を getPhotoEntry() メソッドを使って取得し、そしてそのオブジェクトの delete() メソッドを呼び出します。リスト 8 はこのプロセスを示しています。

リスト 8: 写真を削除する
<?php
// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');

// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);

// get photo entry
// delete entry
try {
  $photo = $gphoto->getPhotoEntry( 'http://picasaweb.google.com/data/entry/api/
  user/xxxxx/albumid/yyyyy/photoid/zzzzz');
  $photo->delete();
} catch (Zend_Gdata_App_Exception $e) {
  echo "Error: " . $e->getResponse();
}        
echo 'Photo successfully deleted!';  
?>

写真を編集する場合にも、同じく getPhotoEntry() メソッドを使います。この場合には、さまざまなオブジェクト・プロパティーに対して新しい値を設定したら、そのオブジェクトの save() メソッドを呼び出し、変更した結果をサーバーに保存します。リスト 9 はこのプロセスを示しています。

リスト 9; 写真を更新する
<?php
// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');

// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);

// get photo entry
// delete entry
try {
  $photo = $gphoto->getPhotoEntry('http://picasaweb.google.com/
  data/entry/api/user/xxxxx/albumid/yyyyy/photoid/zzzzz');

  // set new title
  $photo->setSummary($gphoto->newSummary('New title'));
  
  // set new tags
  $photo->mediaGroup = new Zend_Gdata_Media_Extension_MediaGroup();
  $keywords = new Zend_Gdata_Media_Extension_MediaKeywords();
  $keywords->setText('new,tags');
  $photo->mediaGroup->keywords = $keywords;
  
  $photo->save();
} catch (Zend_Gdata_App_Exception $e) {
  echo "Error: " . $e->getResponse();
}        
echo 'Photo successfully modified!';  
?>

フィードの結果をフィルタリングする

Picasa Web Albums Data API を使うと、フィードをカスタマイズすることもできます。フィードの中のエントリーの数を制限したり、検索基準に一致するエントリーのみを受信したりするようにもできます。例えばリスト 10 に示すように、フィード URL に「max-results」パラメーターを追加すると、フィード・レスポンスの中に返されるエントリーの数を制限することができます。

リスト 10: フィードの結果を制限する
<!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>Restricting feed results</title>
    <style>
    body {
      font-family: Verdana;      
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    img {
      float: left;  
    }
    </style>    
  </head>
  <body>
    <?php
    $userid = 'userid%40googlemail.com';
    $album = 'France2008';
    
    // build feed URL
    $feedURL = "http://picasaweb.google.com/data/feed/api/
    user/$userid/album/$album?max-results=3";
    
    // read feed into SimpleXML object
    $sxml = simplexml_load_file($feedURL);
    
    // get album name and number of photos
    $counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    $total = $counts->totalResults; 
    ?>
    <h1><?php echo $sxml->title; ?></h1>
    <?php echo $total; ?> photo(s) found.
    <p/>

    <?php    
    // iterate over entries in album
    // print each entry's title, size, dimensions, tags, and thumbnail image
    foreach ($sxml->entry as $entry) {
      $title = $entry->title;
      $summary = $entry->summary;
      
      $gphoto = $entry->children('http://schemas.google.com/photos/2007');
      $size = $gphoto->size;
      $height = $gphoto->height;
      $width = $gphoto->width;
      
      $media = $entry->children('http://search.yahoo.com/mrss/');
      $thumbnail = $media->group->thumbnail[1];
      $tags = $media->group->keywords;
      
      echo "<h2>$summary</h2>\n";
      echo "<table><tr><td><img src=\"" . 
      $thumbnail->attributes()->{'url'} . "\"/></td>\n";
      echo "<td><span class=\"attr\">File</span>: $title 
      <br />\n";
      echo "<span class=\"attr\">Size</span>: $size 
      ($height x $width) <br />\n";
      echo "<span class=\"attr\">Tags</span>: $tags 
      </td></tr></table>\n";
    }
    ?>
    
  </body>
</html>

あるいは、q パラメーターを使うことで、ある特定のクエリー・ストリングに一致するエントリーのみを取得するようにもできます。Picasa は各写真のタイトル、説明、タグを検索し、クエリー・ストリングと一致する結果を返します。リスト 11 は、「church」というタグを持つすべての写真を表示する例を示しています。

リスト 11: キーワードを使って写真を検索する
<!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 photos by tag</title>
    <style>
    body {
      font-family: Verdana;      
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    img {
      float: left;  
    }
    </style>    
  </head>
  <body>
    <?php
    $userid = 'userid%40googlemail.com';
    $album = 'France2008';
    
    // build feed URL
    $feedURL = "http://picasaweb.google.com/data/feed/api/user/
    $userid/album/$album?tag=church";
    
    // read feed into SimpleXML object
    $sxml = simplexml_load_file($feedURL);
    
    // get album name and number of photos
    $counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    $total = $counts->totalResults; 
    ?>
    <h1><?php echo $sxml->title; ?></h1>
    <?php echo $total; ?> photo(s) found.
    <p/>

    <?php    
    // iterate over entries in album
    // print each entry's title, size, dimensions, tags and thumbnail image
    foreach ($sxml->entry as $entry) {
      $title = $entry->title;
      $summary = $entry->summary;
      
      $gphoto = $entry->children('http://schemas.google.com/photos/2007');
      $size = $gphoto->size;
      $height = $gphoto->height;
      $width = $gphoto->width;
      
      $media = $entry->children('http://search.yahoo.com/mrss/');
      $thumbnail = $media->group->thumbnail[1];
      $tags = $media->group->keywords;
      
      echo "<h2>$summary</h2>\n";
      echo "<table><tr><td><img src=\"" . 
      $thumbnail->attributes()->{'url'} . "\"/></td>\n";
      echo "<td><span class=\"attr\">File</span>: $title 
      <br />\n";
      echo "<span class=\"attr\">Size</span>: $size 
      ($height x $width) <br />\n";
      echo "<span class=\"attr\">Tags</span>: $tags 
      </td></tr></table>\n";
    }
    ?>
    
  </body>
</html>

すると図 7 のような結果が表示されます。

図 7. キーワードを使って写真を検索する
キーワードを使って写真を検索する
キーワードを使って写真を検索する

Picasa のアクションを統合する

さて、すべての情報を総合して実用的に使うための準備が整いました。Picasa Web Albums Data API に用意された機能と組み合わせることで、指定されたアルバムの写真の表示、削除、追加、そして検索を行える PHP ベースの単純なアプリケーションを作成することができます。このプロトタイプ・アプリケーションには次の 3 つのスクリプトがあります (「ダウンロード」を参照)。

  • 「list.php」-- アルバムの中にある写真を一覧表示し、写真を検索、追加、削除するためのリンクを提供します。
  • 「add.php」-- 新しい写真を追加するためのフォームを表示し、送信されたフォームの処理をします。
  • 「delete.php」-- 指定された写真を削除します。

まず「list.php」(リスト 12) から始めましょう。list.php は各写真が削除用のリンクを持つようにリスト 4 を更新したものです。このページには追加の検索フォームも含まれています。

リスト 12: 写真を一覧表示する
<!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>Listing album contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    img {
      float: left;  
    }
    </style>    
  </head>
  <body>
    <?php
    // load library
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Gdata_Photos');
    Zend_Loader::loadClass('Zend_Http_Client');
    
    // create authenticated HTTP client for Picasa service
    $svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
    $user = "userid@gmail.com";
    $pass = "secret";
    $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
    $gphoto = new Zend_Gdata_Photos($client);
    
    // generate query to get album feed
    $query = $gphoto->newAlbumQuery();    
    $query->setUser("default");
    $query->setAlbumName("France2008");
    
    // filter by search term
    if(isset($_GET['q'])) {
      $query->setQuery($_GET['q']);      
    }
    
    // get and parse album feed
    // get album name and number of photos
    try {
      $feed = $gphoto->getAlbumFeed($query);
    } catch (Zend_Gdata_App_Exception $e) {
      echo "Error: " . $e->getResponse();
    }
    ?>
    <h1><?php echo $feed->getTitle(); ?></h1>
    <?php echo $feed->getTotalResults(); ?> photo(s) found.
    <p/>

    <?php        
    // process each photo entry
    // print each entry's title, size, dimensions, tags, and thumbnail image
    foreach ($feed as $entry) {
      $title = $entry->getTitle();
      $summary = $entry->getSummary();
      $thumbnail = $entry->getMediaGroup()->getThumbnail();
      $tags = $entry->getMediaGroup()->getKeywords();
      $size = $entry->getGphotoSize();
      $height = $entry->getGphotoHeight();
      $width = $entry->getGphotoWidth();
      $photoid = $entry->getGphotoId();
      $albumid = $entry->getGphotoAlbumId();
      
      echo "<h2>$summary</h2>\n";
      echo "<table><tr><td><img src=\"" . 
      $thumbnail[1]->url . "\"/></td>\n";
      echo "<td><span class=\"attr\">File</span>: $title 
      <br />\n";
      echo "<span class=\"attr\">Size</span>: $size bytes 
      ($height x $width) <br />\n";
      echo "<span class=\"attr\">Tags</span>: $tags 
      <br />\n";
      echo "<a href=\"delete.php?aid=$albumid&pid=$photoid\">
       delete photo</a></td></tr></table>\n";
    }
    ?>
    
    <a href="add.php">Add a new photo</a>
    <p/>
    
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">
      Search for photos containing:<br/>
      <input type="text" name="q" size="10"/><p/>
      <input type="submit" name="submit" value="Search"/>
    </form>

  </body>
</html>

図 8 はこのスクリプトを実行した後の表示例を示しています。

図 8. アルバムの写真を一覧表示した Web ページ
アルバムの写真を一覧表示した Web ページ
アルバムの写真を一覧表示した Web ページ

リスト 12 を見るとわかるように、この検索フォームは送信の際に単に list.php を呼び出して、リクエストされるフィードに対して、ユーザーが入力したクエリー・ストリングを (そのクエリー・オブジェクトの setQuery() メソッドを使って) 追加しています。

add.php スクリプトは新しい写真を追加します (リスト 13)。

リスト 13: 新しい写真を追加する
<!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>Adding photos to an album</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <h1>Add Photo</h1>
    <?php if (!isset($_POST['submit'])) { ?>
    <form method="post" action="<?php 
    echo htmlentities($_SERVER['PHP_SELF']); ?>" enctype="multipart/form-data">
      Title: <br/>
      <input name="title" type="text" size="25" /><p/>
      File to upload: <br/>
      <input name="photofile" type="file" /><p/>      
      Tags: <br/>
      <input name="tags" type="text" size="25" /><p/>
      <input name="submit" type="submit" value="Save" />
    </form>
    <?php
    } else {
      // load classes
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Gdata');
      Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
      Zend_Loader::loadClass('Zend_Gdata_Photos');
      Zend_Loader::loadClass('Zend_Http_Client');
      
      // connect to service
      $svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
      $user = "userid@gmail.com";
      $pass = "secret";
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
      $gphoto = new Zend_Gdata_Photos($client);
      
      // validate input
      if (empty($_POST['title'])) {
        die('ERROR: Missing title');
      } 
      
      // sanitize input
      $title = htmlentities($_POST['title']);
      $tags = htmlentities($_POST['tags']);

      // set album name
      $albumName = "France2008";

      // construct photo object
      // save to server      
      try {        
        $photo = $gphoto->newPhotoEntry();
        
        // set file
        $file = $gphoto->newMediaFileSource($_FILES['photofile']['tmp_name']);
        $file->setContentType("image/jpeg");
        $photo->setMediaSource($file);
        
        // set title
        $photo->setSummary($gphoto->newSummary($title));
        
        // set tags
        $photo->mediaGroup = new Zend_Gdata_Media_Extension_MediaGroup();
        $keywords = new Zend_Gdata_Media_Extension_MediaKeywords();
        $keywords->setText($tags);
        $photo->mediaGroup->keywords = $keywords;
        
        // link to album
        $album = $gphoto->newAlbumQuery();        
        $album->setUser($user);
        $album->setAlbumName($albumName);
        
        // save photo
        $gphoto->insertPhotoEntry($photo, $album->getQueryUrl()); 
      } catch (Zend_Gdata_App_Exception $e) {
        echo "Error: " . $e->getResponse();
      }
      echo 'Photo successfully added!';      
    }
    ?>
  </body>
</html>

図 9 はこのフォームを示しています。

図 9. 新しい写真を追加するための Web フォーム
新しい写真を追加するための Web フォーム
新しい写真を追加するための Web フォーム

写真を削除する場合には、GET メソッドを使って、アルバムと写真それぞれに固有の ID を list.php から取得する delete.php スクリプトを使います。delete.php スクリプトはこの情報を使って、該当する写真のエントリーを見つけて削除します。リスト 14 はこのコードを示しています。

リスト 14: 写真を削除する
<?php
// check for album and photo ID 
if (empty($_GET['aid']) || empty($_GET['pid'])) {
  die('ERROR: Missing input parameters');
} else{
  $aid = htmlentities($_GET['aid']);  
  $pid = htmlentities($_GET['pid']);  
}

// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');

// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);

// get photo entry
// delete entry
try {
  $photo = $gphoto->getPhotoEntry('http://picasaweb.google.com/data/
  entry/api/user/userid/albumid/' . $aid . '/photoid/' . $pid);
  $photo->delete();
} catch (Zend_Gdata_App_Exception $e) {
  echo "Error: " . $e->getResponse();
}        
echo 'Photo successfully deleted!';  
?>

まとめ

ここまでの数ページでは、SimpleXML および Zend クライアント・ライブラリーの両方を使って Picasa Web Albums サービスのデータを PHP アプリケーションに統合する方法の集中コースを学んできました。この記事で説明した例では Picasa のフィード・フォーマットを紹介し、以下の方法について説明しました。

  • アルバムと写真の一覧を取得する方法
  • アルバムと写真の一覧を検索用語によってフィルタリングする方法
  • 写真を追加、変更、削除する方法
  • Picasa サービスへのカスタム・インターフェースを作成する方法

これらの例からわかるように、Picasa Web Albums Data API は、写真の管理と保存のための創造的な新しいアプリケーションを作成する上での強力で柔軟なツールです。少し時間をかけて Picasa Web Albums Data API を試し、どんなものかを実感してください。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Open source, Web development
ArticleID=345945
ArticleTitle=Picasa Web Albums を使って PHP アプリケーションを作成する
publish-date=09162008