PHP

Zend Framework での Amazon ItemSearch with PEAR Pager

最近個人ワークで Amazon を使ったモノを2つ程作っていますが、1つは Zend Framework を使用して開発中。 Services_Amazon の itemSearch を使用し商品検索を行っていましたが、Zend Framework 内で各ページ 10 件表示を PEAR Pager の GET の処理で行った際に少し悩んでしまったのでメモ。


Zend Framework の細かい仕様はここでは省きますが、Zend Framework は MVC パターンに基づいて Zend_Controller_Front が URL を分析しディスパッチ処理・ルーティング処理を行います。例えば今回の URL が http://www.test.com/amazon/search/ だとすると AmazonController class 内のsearchAction 関数内で処理を行うのですが、下記の様に Pager のオプションで append を false に、fileName に GET の変数値を表す "%d" を明確に「?pageID=%d」の様に追加しないとうまく動きませんでした。


(ソースは簡略化してあります。)
$amazon =& new Services_AmazonECS4(あなたの Subscription ID);
$amazon->setAssociateID(あなたの Associate ID);
$amazon->setLocale('JP');

$options = array();
$options['Keywords'] = 'flash';
$options['Sort'] = 'salesrank';
$options['ResponseGroup'] = 'Medium';
if(isset($_GET['pageID'])) {
$options['ItemPage'] = $_GET['pageID'];
} else {
$options['ItemPage'] = 1;
}

$rs =& $amazon->itemSearch('Books', $options);

$params = array(
'itemData' => itemData 用の配列,
'perPage' => 10,
'delta' => 5,
'urlVar' => 'pageID',
'path' => 'http://www.test.com/amazon/result/',
'fileName' => '?pageID=%d',
'append' => FALSE,
'httpMethod' => 'GET',
);

$o_pager =& Pager::factory($params);
$navi = $o_pager->getLinks();
$pageNavi = $navi['all'];

こうすることで、URL が 2 ページ目から http://www.test.com/amazon/result/?pageID=2(3,4,5・・・)の様になるので無事に Services_Amazon の $options['ItemPage'] の値に GET 変数を渡すことが可能です。

今回は append を TRUE 、fileName を空白にして、デフォルトではhttp://www.test.com/amazon/result/index.php?pageID=2 になったり、append を FALSE 、fileName を空白にして http://www.test.com/amazon/result/ で GET 変数が渡らなくなったりと Zend Framework 内で上手く挙動させれなかったのですが、検索して %d が 変数値だと分かり上記の設定で解決しました。

ページの一番上へ移動

Jugem x ASK.JP

久々のブログエントリー。


そして久々に会社の既存サービスに Flash を一切使わない機能をゴリゴリ開発。
ブログサービス jugemASK.JP の動画投稿 API を使用してローカル動画投稿機能を実装してみました。Open な API では無いですがよく出来ている API だったので、スムーズに開発出来ました。既存のサービスのソースも追えたので、結構良い勉強になりました。


Jugem x ASK.JP


【使用技術】
PHP、Smarty、PEAR、MySQL、CSS、Javascript、HTML、PhotoShop、ASK API


【担当領域】
PHP、Smarty、PEAR、MySQL、Javascript、ASK API 辺り

ページの一番上へ移動

HTTP_Request で HTTP レスポンス情報の評価

明けましておめでとうございます。

前回に引き続き、flickr.interestingness.getList API と Flash の関係について。
flickr.interestingness.getList はクオリティの高い写真を日付ごとに最大 500 件取得できる点ですが、中には Source URL で取得出来る最も重要な b サイズ(でかい画像サイズ)の画像がアップロードしたユーザーが画像を削除した際に取得出来ない場合があるようで、過去にさかのぼるにつれてその頻度は高いようです。
Flash で Viewer を作る以上、そういった画像は極力省きたいので一度 PHP などのプログラム側で HTTP レスポンスからの情報を評価する必要があります。Flickr の仕様上、画像が存在しない場合はHTTP リスポンスコードで 302(Moved Temporarily)が返って画像が無い場合の GIF 画像(photo_unavailable.gif)が返ってしまうので、Flash ではこういった GIF 画像も画像と認識して読み込んでしまい表現上都合が良くないので、cron で定期的にそういった画像を省いた状態で新規に xml を新たに書き出した方が良さそう。でもいちいちリクエストをするので処理は重いのがネックですね。curl --head でも同様な処理を行ったがそんなに処理速度が変わらなかった。何か他の方法は無いだろうか。

この記事の続きを読む »

ページの一番上へ移動

Zend_Amf_Server + AS3

個人的に勉強していた Zend_Amf_Server を実レベルの仕事で初めて Flash Remoting として使ってみた。プロジェクトは Flash ゲームで、もう 1 人の Flash デベロッパーと連携してゲーム以外の AS3 のバックエンド/モデルクラス/ビュークラス/コントローラ系のプログラム、Remoting 系、PHP/MySQL 開発、サーバ少々を担当。

Zend_Amf_Server は物凄くいいですね。何がいいかって Zend を普通のウェブアプリケーション感覚で開発できるので連携するバックエンド部分を MVC で組めるし、Zend_View_Smarty とか Zend_Db_Table とか Zend_Registry とか Flash と連携することを意識しないで使えるから超楽だ。Zend を使ってる Flash デベロッパーなら学習コストなし。PHP/MySQL 系のウェブアプリケーションに作っていた Zend のクラス群を Flash Remoting 用にそのまま引っ張ってきて再利用できたので、よっぽどシステムがでかくなければ簡単に作れちゃう感じですな。

で、Zend_Amf_Server で注意したい点を忘れないようにメモッておく。

この記事の続きを読む »

ページの一番上へ移動

Zend_Paginator を使ってみる。

こんにちわ。
Sydney に渡って前半開発に頑張りすぎて肩こりが酷くなったので、たまには運動しないとと思い最近 15 年くらいやってて多少自信があったスケボーを購入してやり始めたんですが、2 週間目で疲労骨折気味になってしまい、全く動けなくなっている convexstyle です。意味ねえ…

・・・・・

最近のプロジェクトで Zend_Paginator を初めて使ってみました。
今までは PEAR::Pager を使っていたけど、Zend Framework に入ってなかなか便利だというのを聞いていたので使ったが便利だった。

Zend_Paginator_Adapter_DbSelect はかなり良いらしいが、今回は CMS の API 経由で XML をパースして表示する形式だったので、シンプルに Zend_Paginator_Adapter_Array をアダプタとしては使用した。

ページにどの様に表示するかは CSS/XHTML とテンプレートエンジン(Smarty など)の問題なので、色々やり方はあるしそこまで重要では無いが、重要な点はどの様に URI の syntax をテンプレートエンジンのレンダリング結果に受け渡すかだろう。

まずはどの様な値が Zend_Paginator から返されるか dump してみる。

$_paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($_data));
$_paginator->setCurrentPageNumber($_pageId);
$_paginator->setItemCountPerPage($this->_pagerIni->blog_per_page);
$_paginator->setPageRange($this->_pagerIni->page_range);
Zend_Debug::dump($_paginator->getPages('Sliding'));

結果は stdClass 形式で下記の様に返される。

object(stdClass)#69 (12) {
  ["pageCount"]=>
  int(1)
  ["itemCountPerPage"]=>
  int(3)
  ["first"]=>
  int(1)
  ["current"]=>
  int(1)
  ["last"]=>
  int(1)
  ["pagesInRange"]=>
  array(1) {
    [1]=>
    float(1)
  }
  ["firstPageInRange"]=>
  float(1)
  ["lastPageInRange"]=>
  float(1)
  ["currentItemCount"]=>
  int(2)
  ["totalItemCount"]=>
  int(2)
  ["firstItemNumber"]=>
  int(1)
  ["lastItemNumber"]=>
  int(2)
}

この記事の続きを読む »

ページの一番上へ移動

Zend_Service_ReCaptcha を使ってみる。

Optical Character Recognition 技術で有名な悪意ユーザーを退治する ReCaptcha が Zend_Service に知らないうちに組み込まれてたんでプロジェクトに使ってみる。かなりシンプルな API 対応なんで想像つくけど、あるもんは使う。

Recaptcha

reCAPTCHA でアカウントを作って、Public Key と Private Key を作成。
これを ini ファイルに設定して、こんな感じで設定。

$_params = array(
    'theme' => 'blackglass'
);
$this->_recaptcha = new Zend_Service_ReCaptcha($this->_recaptchaIni->public_key, $this->_recaptchaIni->private_key);
$this->_recaptcha->setOptions($_params);

View には

$this->view->_recaptcha = $this->_recaptcha->getHtml();

後は変数に post された際に下記な感じか。

if($_req->isPost()) {
    $_recaptcha_challenge_field = $_req->getPost('recaptcha_challenge_field');
    $_recaptcha_response_field  = $_req->getPost('recaptcha_response_field');
    $_recaptchaResult = $this->_recaptcha->verify(
        $_recaptcha_challenge_field,
        $_recaptcha_response_field
    );			
    if(!$_recaptchaResult->isValid()) {
        $_msg = 'reCaptcha field is needed to be filled correctly.';
        array_push($this->_errors, $_msg);
    }			
    if(!empty($this->_errors)) {					
        return;
    }
}

楽やな。

・・・・・

海外に来て、日本じゃあまり聞いたことの無いサービスの API に連携しないといけない事が多々ある。自分だけ知らないのかもしれないが。Silverpop がその1つ。メーリングリスト系のウェブサービスらしい。さすがにこれは Zend_Service に無かった。PHP 系のサイト制作には高頻度使用なので、自作しよう。

日本ではあり得ない仕様が海外だと結構あり得たりする。
ここら辺は本当にむずい。そのうちここら辺については書こう。

ページの一番上へ移動

PHP と AS3 の Namespace の処理

PHP/AS3 共に XML Namespace の記述方法をいつも忘れるのでメモ。
今回の目標は Flickr の latest XML から <media:thumbnail> の url と width と height を取得すること。

AS3 の場合は Namespace オブジェクトを作成し、それを基に特定のノードにアクセスする。

var _xml:String            = "http://api.flickr.com/services/feeds/photos_public.gne?id=53418554@N00&lang=en-us&format=rss_200";
var _urlRequest:URLRequest = new URLRequest();
_urlRequest.url            = _xml;
var _urlLoader:URLLoader   = new URLLoader();
_urlLoader.addEventListener(Event.COMPLETE, _loadCompleteHandler, false, 0, true);
_urlLoader.load(_urlRequest);
function _loadCompleteHandler(evt:Event):void
{
	var _xml:XML = XML(evt.target.data);
	_parseXml(_xml);
}
function _parseXml(xml:XML):void
{
	var _media:Namespace  = new Namespace("http://search.yahoo.com/mrss/");
	var _mainNodeNum:uint = xml..item.length();
	for(var _i:uint = 0; _i < _mainNodeNum; _i ++)
	{
		var _item:XML = xml..item[_i];
		var _thumbnail:String       = _item._media::thumbnail.@url;
		var _thumbnailWidth:Number  = _item._media::thumbnail.@width;
		var _thumbnailHeight:Number = _item._media::thumbnail.@height;
		trace(_thumbnail, _thumbnailWidth, _thumbnailHeight);
	}
}

PHP の場合は SimpleXMLElement オブジェクトの registerXPathNamespace メソッドを使う。
今回は Zend_Http_Client と絡めて使ってみる。

require_once('Zend/Http/Client.php');
$_gatwayUri = 'http://api.flickr.com/services/feeds/photos_public.gne?id=53418554@N00&lang=en-us&format=rss_200';
$_client    = new Zend_Http_Client($_gatwayUri);
$_response  = $_client->request('GET');
if($_response->isSuccessful()) {
    $_body = $_response->getBody();
    if(strlen($_body) > 0) {
        $_xml = simplexml_load_string($_body);
        $_xml->registerXPathNamespace('media', 'http://search.yahoo.com/mrss/');
        $_items = $_xml->xpath('/rss/channel/item');
        foreach($_items as $_item) {
            $_content      = $_item->xpath('media:thumbnail');
            $_thumbnailObj = $_content[0];
            $_thumbnail    = (string) $_thumbnailObj['url'];
            $_width        = (integer) $_thumbnailObj['width'];
            $_height       = (integer) $_thumbnailObj['height'];
            echo '<pre>';
            var_dump($_thumbnail);
            var_dump($_width);
            var_dump($_height);
            echo '</pre>';
        }
    }
}

あー、忘れる。

ページの一番上へ移動