08
2月
CakePHPでAmazon Web Service
CakephpでAmazon Web Serviceを利用するためにモデルをうまく使います。今回はPEARのServices_Amazonは使いません。賛否両論あるかもしれませんが、依存しまくりのライブラリを安易に使うと運用上ダルくなるので僕はなるべく使いません。ネット上にはPEARを使う方法のほうが多いし。
では、まずはデータベースを使用しないようにモデルを書きます。
/app/models/test.php
class Test extends AppModel
{
var $name = 'Test';
var $useTable = false;
}
次にAmazon Web Serviceへアクセスするメソッドを実装します。
/cake/libs/model/app_model.php
class AppModel extends Model
{
var $xml;
var $host = "ecs.amazonaws.jp";
var $base_path = "/onca/xml?Service=AWSECommerceService";
var $sub_id = "自分のアクセスID";
var $aid = "自分のアソシエイトID";
var $version = "2007-10-29";
var $contentType= "text/xml";
var $path = "";
function setKeyword($keyword, $index, $page)
{
$this->path = $this->base_path
. "&AWSAccessKeyId=" . $this->sub_id
. "&AssociateTag=" . $this->aid
. "&Version=" . $this->version
. "&ContentType=" . $this->contentType;
$this->path .= "&Operation=ItemSearch"
. "&ResponseGroup=Small,Offers,Images,BrowseNodes,SalesRank"
. "&Keywords=" . $keyword
. "&SearchIndex=" . $index
. "&Page=" . $page;
return true;
}
function loadXml()
{
$doc = $this->connect();
if(!$doc) return false;
if(substr($doc,0,5) != "<?xml") return false;
$this->xml = simplexml_load_string($doc);
return $this->xml;
}
function connect()
{
$sockPointer = fsockopen($this->host, 80, $errno, $errstr, 6);
if(!$sockPointer)
{
return false;
}
else
{
stream_set_timeout($sockPointer, 6, 0);
fputs ($sockPointer, "GET $this->path HTTP/1.0rnHost: $this->hostrnrn");
fputs ($sockPointer, "User-Agent: AwsDataSourcenn");
fputs ($sockPointer, "Keep-Alive: 300nn");
fputs ($sockPointer, "Connection: Keep-Alivenn");
fputs ($sockPointer, "Referer: http://www.artsnet.jp/nn");
$buf = "";
$response = fgets($sockPointer);
if(substr_count($response, "200 OK") > 0)
{
while(!feof($sockPointer))
{
$buf = $buf . fread($sockPointer,4096);
}
}
else
{
$result = false;
}
$result = true;
}
fclose($sockPointer);
if($result)
{
$doc = substr($buf, strpos($buf,"rnrn")+4);
return $doc;
}
else
{
return false;
}
}
}
ちなみにこのコードはWebサービスをAmazonで知る――PHPでECS 4.0を使うテクニックそのまんまです。
最後にコントロールで使います。
/app/model/controllers/tests_controller.php
class TestsController extends AppController
{
var $name = 'Tests';
function index()
{
$this->Test->setKeyword('PHP', 'Books', '1');
$this->Test->loadXml();
print_r($this->Test->xml);
}
}
ちなみにCakePHPで楽天WEBサービスを使うのコメント欄でCakePHPのdatasourceをうまく使うヒントが書かれていました。これはデータ操作の全てをdatasourceに追いやることで、データ自体がRDBだろうがXMLだろうがJSONだろうが同じように使うためのものです。逆に言えばCakePHPでRDBを扱ってきたsetとかfindとか全てのメソッドが通るように実装しなければならないことを意味します。
今回はそんな必要も時間もないのでApp_modelで実装するだけにしました。
トラックバックありがとうございます。
2月 9th, 2009 at 8:19 AMapp_model.phpにまとめると便利ですね。
こういうやり方もあるんだと、勉強になりました。