連載:AjaxとPHPでリッチクライアント(1)

Ajaxを使ったamazon検索をPHPで作ろう


上鍵 忠志
日本PHPユーザ会
2005/10/4

 Amazon商品検索フォームに
 GoogleSuggestCloneJaxを改造する

■AmazonSuggestCloneJaxを作成する

 

 Amazon商品検索を、AjaxACのサンプルのGoogleSuggestCloneJaxを改造して作ってみよう。この改造はGoogleSuggestCloneJaxをベースに日本Amazonの商品を検索するフォームになる。

 なお、AmazonSuggestCloneJaxの名前は単にGoogleSuggestCloneJaxのGoogleをAmazonに変更しただけで特に理由はない。

 GoogleSuggestCloneJaxから比較すると、以下の変更だけである。

・index.phpのほぼ全面書き直し
・GoogleSuggestCloneJax::getSuggestions()の全面書き直し

 なお、問い合わせ先はMySQLではなく日本amazon(amazon.co.jp)になるので、SQLなどは必要ない。ただし、PEAR::Services_Amazonを必要とするのでインストールしておこう。

 また、Services_Amazonは正式版どころかまだalpha版でもないのでパッケージ名にバージョン番号を付加しなければインストールできない。PHPのバージョンやインストール済の各種PEARパッケージのバージョンによってはうまくインストールできない場合があるかもしれない。筆者の環境(CentOS 4.1)では下記の順番PEARパッケージをインストールすることでServices_Amazonをインストールできた。

Services_Amazonのインストール
# pear upgrade XML_Parser Net_Socket
# pear install XML_Util XML_Serializer-beta
# pear install Net_URL
# pear install HTTP_Request HTTP_Client
# pear install Services_Amazon-0.2.0

 最近のpearコマンドはinstallに--alldepsサブオプションを付加することで、芋づる式に依存関係を解決してくれるのだが、Services_Amazonに関しては最終的に依存解決を行うことができなかった。また、日本AmazonのWebサービスを使うためにアソシエイトIDとSubscription IDを取得しなければならない(通常、申請すれば簡単にIDが発行される)。

AmazonのアソシエイトIDとSubscription IDを取得する

 それではまずindex.phpである。これは比較的多く改変をしている。

著者が作成したindex.phpサンプル

 Amazonの検索情報としてindex.phpの45行目とGoogleSuggestCloneJax.class.phpの192行目を修正する。

修正例
$amazon = &new Services_Amazon('<自分のSubscription ID>', '<自分のアソシエイトID>', 'jp', 'http://xml.amazon.co.jp/onca/xml2')

 前半がAjaxACを用いた検索関連の処理、後半がServices_Amazonを用いたamazon.co.jpの検索結果の表示である。

 次にバックエンドのGoogleSuggestCloneJax.class.phpである。下記はGoogleSuggestCloneJax::getSuggestions()の抜粋である。

GoogleSuggestCloneJax.class.phpの抜粋(amazonとのアクセス部分)
function getSuggestions($prefix, &$arr)
{
  $amazon = &new Services_Amazon('0AW6NMZ572Z4M7VHCRR2',
      'yokukitanaii-  22', 'jp',
      'http://xml.amazon.co.jp/onca/xml2');
  $products = NULL;
  $prefix = ltrim(preg_replace('/[^a-z0-9_. ]/', '',
      strtolower($prefix)));
  $prefix = preg_replace('/\s+/', ' ', $prefix);
  $products = $amazon->searchKeyword($prefix,
      'All Modes', 1);
  if(PEAR::isError($products)) {
     $arr[] = array( $prefix, "Error:".$products->message);
  } else {
    for ( $i = 0; $i < $this->suggestion_limit && empty( $products[ $i]) != TRUE; $i++) {
      if ( empty( $products[ $i][ "name"]) != TRUE) {
        $arr[] = array(
            htmlspecialchars($products[ $i][ "name"]),
            $products[ $i][ "listprice"]);
      }
    }
  }
}

 これは単にamazon.co.jpから商品の情報を取得し、$arrという変数に格納していっているだけだ。なお、このGoogleSuggestCloneJax特有の配列の使用法で、$arrにはarray( "左側の文字列", "右側の文字列")を入れなければいけないようになっている。また、両要素とも必ず文字列でなければならない。

 GoogleSuggestCloneJaxは以下のようになっていれば問題ないだろう。

$arr[]の例
$arr[] = array( "Japanese", "10000");
$arr[] = array( "English", "7000");

 今回はAmazon.co.jpからの返り値から、商品名と商品価格をそれぞれ格納した。

また、途中に

$prefix = preg_replace_callback( "/%u[0-9A-Za-z]{4}/",
      array( $this, "escapeToUtf8"), $prefix);

というコードがあるが、amazonは日本語などのマルチバイトは「%u####」というエスケープされた文字列を返してくるので、UTF-8に変換する関数「escapeToUtf8」を呼び出している。

GoogleSuggestCloneJax.class.phpの抜粋(文字エンコードの変換部分)
// %u####というエスケープコードをUTF-8エンコードに戻す
function escapeToUtf8( $codes) {
  $char = "";
  foreach( $codes as $code){
    $code = intval( substr( $code, 2), 16);
    if( $code &lt; 0x7F) { // 7bit
      $char .= chr( $charcode);
    } else if ( $charcode &lt; 0x800) { // 14bit
      $char .= chr(0xC0 | ($charcode / 64));
      $char .= chr(0x80 | ($charcode % 64));
    } else {
      $char .= chr(0xE0 | (($charcode / 64) / 64));
      $char .= chr(0x80 | (($charcode / 64) % 64));
      $char .= chr(0x80 | ($charcode % 64));
    }
  }
  return $char;
}

 最後にAjaxACのキーハンドリングでは日本語が入力された場合に不都合がある。これは英数字などの入力が前提になっている部分があるためだ。

 これはgooglesuggestclone.jsの7行目あたりの修正で対処できる。

修正元のコード
if (q.length == 0) || !gsc_basicmatch.test(q)) {
修正後のコード
if (q.length == 0) {

 これで日本語のみの入力でもamazonへの検索が実行される。残念ながらWebサービスではソートなどの機能がなかったり、検索キーワードの状態を指定したり(全文一致や方向一致など)できないため、あまり思ったとおりの検索結果にはならないが、うまくやれば面白いことができるかもしれない。

   まとめ

 AjaxACはバックエンドはAjaxACApplicationというクラスを基にリクエストを処理する。このクラスは若干複雑なので、次回以降での説明に回す。フロントエンドはおおむね下記のように処理をする。

index.phpのひな型例
// AjaxACApplicationの派生クラス
$ajax = &new GoogleSuggestCloneJax();
$ajax->handleRequest();
// Ajax初期化コード出力
$ajax_core = $ajax->loadJsCore(true)
echo <<<EOD
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>amazon検索</title>
<!-- AjaxACフロントエンドコア -->
$ajax_core
<!-- 表示関連CSS -->
<link rel="StyleSheet" type="text/css" href="googlesuggestclone.css" />
</head>
<body>
<form>...</form>
EOD;
// フォームとイベント要素名の関連付け
echo $ajax->attachWidgets( array( ...));
// Ajax実処理コード出力
echo $ajax->loadJsApp(true);

 これだけだとテキストフィールドが1つのインクリメンタル検索のようなものしかできないが、自分が運用しているブログや掲示板に検索結果を付加する場合には十分だろう。

 Ajaxはその技術上、それを前面に出したコンテンツを作ることがすべてではなく、あくまでユーザーインターフェイスの向上のための技術の1つということを忘れてはいけない。

 次回はAjaxACもしくは別のライブラリを掘り下げてより積極的に複雑なAjaxを実現してみたいと思う。

3/3 次回もお楽しみに

 INDEX

Ajaxを使ったamazon検索をPHPで作ろう
  Page1<AjaxとPHPの関係>
PHPとAjaxの関係/Ajaxを使ったウェブアプリケーションの例/Ajaxを用いたアプリケーションの可能性/Ajaxを扱うためのPHPライブラリたち
  Page2<AjaxACを使う>
サンプルを使用し、改造してみる/CountryRegionCityJax/GoogleSuggestCloneJax
Page3<Amazon商品検索フォームにGoogleSuggestCloneJaxを改造する>
AmazonSuggestCloneJax


HTML5 + UX フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日 月間