2010年02月26日

PEAR Services_Amazon を使ってみる

 楽天ウェブサービスが安定しないこともあり(新規デベロッパーIDの発行を停止したようですね)、Amazon を併用するようにしたのですが、せっかくなので、新しいことを試してみようと、PEAR Services_Amazon を使ってみることにしました。書籍検索の場合は、以下のような感じです。

require_once 'Services/Amazon.php';
require_once 'Cache.php';

$access_key_id = '(公開アクセスキー)';
$secret_access_key = '(秘密アクセスキー)';
$associate_tag = '(アソシエイトタグ)';
    
$amazon = new Services_Amazon($access_key_id, $secret_access_key, $associate_tag);
$amazon->setCache('file', array('cache_dir' => '(キャッシュの保存先)'));
$amazon->setCacheExpire(3600); // 秒数で指定
$amazon->setLocale('JP');

$options = array();
    
$options['ResponseGroup']  = 'Medium'; //取得したい情報
$options['Keywords']       = '検索したいキーワード';
$options['Sort']           = 'salesrank';

$result = $amazon->ItemSearch('Books', $options);

if (PEAR::isError($result)) {
        echo $result->message;
} else {
    foreach($result['Item'] as $item) {
        $ItemData[] = array(
            'ImageURL' => $item["SmallImage"]["URL"],    
            'DetailPageURL' => $item["DetailPageURL"],
            'Title' => $item["ItemAttributes"]["Title"],
            'Price' => $item["ItemAttributes"]["ListPrice"]["FormattedPrice"]
        );
    }
}

 これで、$ItemData の中に商品データが入るので、適宜加工して表示するような形になります。ちょっと変わったこととしては、キャッシュを使うことによって、同じリクエストを連続して行わないように工夫をしています。この機能を使うためには、Services_Amazon のほかに、Cache のパッケージも必要となります(Cache_Lite ではないので注意)。

 パッケージのドキュメントもクラスのリファレンスしかないため、取っつきにくいですが、電子署名認証を自動でやってくれたり、結果を連想配列で返してくれたりと、かなり使い勝手がよいので、おすすめです。他にも、複数のキーワードについてひとつのリクエストで処理する doBatch メソッドや、複数の操作をひとつのリクエストで処理する doMultiOperation メソッドなども便利だと思います。

posted by まいける at 01:46 | Comment(0) | TrackBack(0) | PHP

2009年11月24日

モバイル版 Google Analytics を PHP4 で動かす

 先日からサービスの提供が始まったモバイル版の Google Analytics ですが、アクセス解析用の PHP スクリプトである ga.php は PHP4 では動きません。PHP4 のアップデートはすでに終わっているので、PHP5 にアップグレードするべきなのですが、レンタルサーバなどで PHP のアップグレードをしてくれないところもあると思います。そこで、PHP4 でも動くように、ga.php を修正してみました(ライセンス的な問題がちょっと気になりますが…)。

 準備として、PEAR の PHP_Compat をインストールします(stable版の1.5.0ではなく、alpha版の1.6.0a2が必要)。

 次に、ga.php の先頭部分に

require_once 'PHP/Compat/Function/setrawcookie.php';
require_once 'PHP/Compat/Function/file_get_contents.php';

を追加します。そして、97行目と100行目にある file_get_contents を php_compat_file_get_contents に書き換えます。さらに、144行目以降を

    setrawcookie(
        COOKIE_NAME,
        $visitorId,
        $timeStamp + COOKIE_USER_PERSISTENCE,
        COOKIE_PATH);

から

    setrawcookie(
        COOKIE_NAME,
        $visitorId,
        $timeStamp + COOKIE_USER_PERSISTENCE,
        COOKIE_PATH,
        '',
        false,
        false);

に変更します。

 これで動くようになるはずです(PHP4.4.9 の環境で確認)。

 種明かしをすると、setrawcookie は PHP5 から新たに登場した関数です。また、file_get_contents のコンテキストサポート(第3引数)も PHP5 以降にサポートされたものです。このため、これらを使えるようにしなければなりません。setrawcookie は、PHP4 にもともとない関数ですので、それほど問題ない(せいぜい 1.6.0a2 をインストールすることと、引数を省略せずに記載することくらい)のですが、file_get_contents は、PHP4.3.0 以降ではすでに登場しているため、PHP_Compat::loadFunction を使う PEAR PHP_Compat の通常の使い方だと、PHP ネイティブの関数が優先されてしまいます。そこで、上記のように個別の関数を手動で読み込んだうえで、PHP_Compat 側の関数を使うようにしているのです。

 不具合等があれば、コメント欄などでご指摘ください。

posted by まいける at 12:32 | Comment(2) | TrackBack(1) | PHP

2009年01月21日

XML_RPC2を使ってみる

 どういうわけか、インストールされていたはずの PEAR XML_RPC が削除されてしまっていたので、代わりに後継といわれる XML_RPC2 を使ってみました。XML_RPC2 は PHP5 専用ですが、PHP4 のサポートも終了しましたし、今後こちらが使われることが増えていくでしょう。

 XML_RPC2 の特徴として、サーバからのレスポンスをキャッシュすることができるというものがあります。これまで、XML_RPC と Cache_Lite を組み合わせて使っていた人からすると、一つで済むので手間がだいぶ省けると思います。

 サンプルとして、Trend Antenna でも使っているはてなダイアリーキーワード連想語APIのサンプルを XML_RPC2 で書いてみようと思います(キャッシュ付き)。

require_once 'XML/RPC2/CachedClient.php';

$options = array(
    'prefix' => 'hatena.',
    'encoding' => 'utf-8',
    'cacheDebug' => false,
    'cacheOptions' => array(
        'cacheDir' => '/tmp/',
        'lifetime' => 21600,
        'automaticCleaningFactor' => 20,
        'hashedDirectoryLevel' => 1,
        'cacheByDefault' => true
    )
);

// XML_RPC2_CachedClient オブジェクトを作成します
$client = XML_RPC2_CachedClient::create('http://d.hatena.ne.jp/xmlrpc', $options);

try {
    $result = $client->getSimilarWord(array('wordlist' => array('Hatena', 'PHP')));
    $ret_val = array_values($result['wordlist']);
} catch (XML_RPC2_FaultException $e) {
    // XMLRPC サーバが XMLRPC のエラーを返しました
    die('Exception #' . $e->getFaultCode() . ' : ' . $e->getFaultString());
} catch (Exception $e) {
    // その他のエラー (HTTP あるいはネットワークの問題など...)
    die('Exception : ' . $e->getMessage());
}

foreach($ret_val as $word) {
    echo $word['word'] . ', ';
}

 こんな感じです。XML_RPC と比べると、XMLRPC の型を意識せずに使えることと、サーバのメソッドをクライアントオブジェクト(例の $client)のメソッドとして呼び出して使うので、スクリプトが見やすいという点が便利だと思います。なお、cacheOptions の中身は、Cache_Lite と同じ部分もあるので、それほど難しくないと思います。

posted by まいける at 08:33 | Comment(0) | TrackBack(0) | PHP

2008年11月12日

波ダッシュ問題 on XML_RPC

 PEAR の XML_RPC には UTF-8 の文字列の取扱いに不具合があるようで、UTF-8 固有の文字を送信すると文字化けします。例えば、タイトルに挙げた波ダッシュや単位記号(cmやkg)などがこれにあたります(波ダッシュについては、Wikipedia の記事が参考になります)。

 解決方法としては、文字列を渡す前にあらかじめ別の文字列に置換しておき、返ってきた結果に対して、逆の置換を行うことが考えられます。例えば、

require_once 'XML/RPC.php';

$str = (XML_RPCに渡す文字列)

// 以下の部分で全角チルダと波ダッシュをいったん naminamimoji に置換
$str = preg_replace('#\xEF\xBD\x9E#i', 'naminamimoji', $str);
$str = preg_replace('#\xE3\x80\x9C#i', 'naminamimoji', $str);

$params = new XML_RPC_Value(
    array(
        'body' => new XML_RPC_Value($str, 'string'),
        'score' => new XML_RPC_Value(50, 'int'),
    ),
    'struct'
);
    
$msg = new XML_RPC_Message('hatena.setKeywordLink', array($params));

$cli = new XML_RPC_Client('/xmlrpc', 'd.hatena.ne.jp');

$resp = $cli->send($msg);

if (!$resp) {
    echo 'Communication error: ' . $cli->errstr;
    exit;
}

if (!$resp->faultCode()) {
    $val = $resp->value();
    $data = XML_RPC_decode($val);
    $ret_val = $data;
        
} else {
    /*
     * xmlrpc.php スクリプトが遭遇した問題を
     * 報告する
     */
    echo 'Fault Code: ' . $resp->faultCode() . "\n";
    echo 'Fault Reason: ' . $resp->faultString() . "\n";
    $ret_val = $data;
}

// 置換していた文字を元に戻す
$ret_val = str_replace('naminamimoji', '〜', $ret_val);
 ただ、この方法は例で挙げたはてなキーワード自動リンクAPIのように、入力される一部の文字を無視しても実用上問題がない場合には効果的ですが、入力される文字列自体が重要な場合(検索など)の場合にはうまくいきません。

 おそらく内部でエンコードの変換を行っていることが原因だと思うのですが、ちょっと困りものです。

posted by まいける at 18:30 | Comment(0) | TrackBack(0) | PHP

2008年06月11日

php.ini

 前回の予告通り、php.ini のお話をしようと思います。

 さくらインターネットの場合、/www/ の直下に php.ini を置くことで、PHP の設定を変更することができます。私の場合は、以下のように設定しています。

short_open_tag = Off
display_errors = On
error_reporting = E_ALL & ~E_NOTICE
output_buffering = Off
output_handler = none
register_globals = Off
magic_quotes_gpc = Off

precision = 12
safe_mode_exec_dir = ""

include_path = ".:/usr/local/php-5.2.6/lib/php:/home/trend-antenna/pear/php"

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = NULL
mbstring.http_input = pass
mbstring.http_output = pass
mbstring.encoding_translation = Off
mbstring.detect_order = UTF-8,EUC-JP,SJIS,JIS,ASCII
mbstring.substitute_character = none;

 前回持ち越しにした、ローカル版の PEAR を使いやすくするための設定は、include_path の部分です。

 他の設定のポイントとしては、register_globals は、セキュリティ上の問題があるので off に、magic_quotes_gpc は、PHP 側で処理を任せると何をしているのか見えにくくなってしまうので off に設定しています。
 mbstring 関係も基本的には PHP 任せにせずに、スクリプトで処理するようにしています。上記の設定項目は、文字コードの自動変換に関係するものが多いのですが、自動変換がはさまることで、かえって文字化けが発生することも少なくないからです。

 あと php.ini 関連で注意すべきところとしては、さくらインターネットの場合、php.ini を置いたときと置かなかったときで設定内容が変わります。私が確認した限りでは、以下のパラメータが異なっていました。

パラメータphp.ini なしphp.ini あり
allow_call_time_pass_referenceOffOn
display_errorsOffSTDOUT
error_logsyslogno value
error_reporting4177no value
extension_dir.//usr/local/php-5.2.6/lib/php/extensions/no-debug-non-zts-20060613
log_errorsOnOff
max_input_time60-1
output_bufferingno value0
precision1214
safe_mode_exec_dirno value/usr/local/php/bin
upload_max_filesize5M2M
mbstring.internal_encodingEUC-JPISO-8859-1
mbstring.languageJapaneseneutral
url_rewriter.tagsa=href,area=href,frame=src,input=src,form=,fieldset=a=href,area=href,frame=src,form=,fieldset=

 php.ini を設定する場合に、上記の項目について何も記述しないと、上記の「php.ini あり」の設定が使用されるため、必要に応じて設定を明示的に書く必要があると思います。

posted by まいける at 00:51 | Comment(0) | TrackBack(0) | PHP

2008年06月09日

PEAR のインストール

 サーバとドメインの設定を終えて、次に何について書こうかと思ったのですが、PEAR のインストールの話にすることにしました。そのほうが他の設定のことをまとめて書けると思うからです。

 というわけで、PEAR のインストールですが、PEAR の Web サイトの「共有ホストでの PEAR のローカルコピーのインストール」のとおりに作業を進めていきます。

 さくらインターネットの PEAR は、初期状態で 1.4 以上なので、まず

%pear config-create /home/trend-antenna .pearrc

を実行して、ローカル設定ファイルを作成します。

 説明ページでは、

%pear config-create /home/user/pear .pearrc

と書かれていますが、これだと、/home/user/pear/pear 以下に各種ファイルがインストールされます。個人的には、あまり階層が深くなりすぎるのもどうかと思いますので、上記のように設定しました。

 あとは、

%pear install -o PEAR

でローカル版の PEAR がインストールされます。

 あとは、好きなパッケージをインストールするだけです。pear install コマンドに -o を付けると、依存するパッケージをまとめてインストールしてくれます。なので、

%pear install -o pear/MDB2#mysql

とすれば、MDB2 と mysql 用のドライバをまとめてインストールすることができます。また、今回のシステムでは Image_Graph を使っているのですが、Image_Graph はアルファ版のため、上記の方法ではインストールできません。エラーメッセージにも書いてあるように

pear install -o channel://pear.php.net/Image_Graph-0.7.2

のように書く必要があります。

 上記の作業でローカルに PEAR のパッケージをインストールすることができます。ただ、スクリプトで利用しようとする場合には、絶対パスで書く必要があり、このままでは不便です。php.ini の設定でこの問題は解決できるのですが、それは次回に。
posted by まいける at 23:43 | Comment(0) | TrackBack(0) | PHP