33.3.3 获得一个AmazonResultSet类

现在,我们来仔细了解getARS()函数,如程序清单33-7所示。

程序清单33-7 cachefunctions.php函数库中的getARS()函数——一个查询的结果集


//Get an AmazonResultSet either from cache or a live query

//If a live query add it to the cache

function getARS($type,$parameters){

$cache=cached($type,$parameters);

if($cache){

//if found in cache

return$cache;

}else{

$ars=new AmazonResultSet;

if($type=='asin'){

$ars->ASINSearch(padASIN($parameters['asin']),$parameters['mode']);

}

if($type=='browse'){

$ars->browseNodeSearch($parameters['browsenode'],

$parameters['page'],$parameters['mode']);

}

if($type=='search'){

$ars->keywordSearch($parameters['search'],$parameters['page'],

$parameters['mode']);

}

cache($type,$parameters,$ars);

}

return$ars;

}


这个函数是用来驱动从Amazon获得数据的操作。它可以以两种方式完成数据获取:从缓存,或者从Amazon实时获得。由于Amazon要求开发人员缓存已经下载的数据,因此这个函数将首先查看保存在缓存中的数据。我们将在稍后的内容详细介绍缓存。

如果我们还没有执行特定的查询操作,就必须从Amazon站点实时获得数据。通过创建一个AmazonResultSet类的实例,并且调用该类中对应于我们需要执行的查询的方法,可以获得实时数据。查询的类型是由$type参数决定的。以种类(或者浏览节点)查询为例,我们将browse传递给该参数——参阅程序清单33-6。如果我们希望执行一个针对特定图书的查询,就应该传递该图书的asin,而如果希望执行一个关键字查询,该参数就必须设置为search。

该参数的每一个不同值都将调用AmazonResultSet类中的不同方法。单个物品搜索将调用ASINSearch()方法。种类搜索将调用browseNodeSearch()方法。而关键字搜索将调用keywordSearch()方法。

下面,我们来仔细了解AmazonResultSet类。该类的所有代码如程序清单33-8所示。

程序清单33-8 AmazonResultSet.php——处理与Amazon站点连接的类


<?php

//you can switch between REST and SOAP using this constant set in

//constants.php

if(METHOD=='SOAP'){

include_once('nusoap/lib/nusoap.php');

}

//This class stores the result of queries

//Usually this is 1 or 10 instances of the Product class

class AmazonResultSet{

private$browseNode;

private$page;

private$mode;

private$url;

private$type;

private$totalResults;

private$currentProduct=null;

private$products=array();//array of Product objects

function products(){

return$this->products;

}

function totalResults(){

return$this->totalResults;

}

function getProduct($i){

if(isset($this->products[$i])){

return$this->products[$i];

}else{

return false;

}

}

//Perform a query to get a page full of products from a browse node

//Switch between XML/HTTP and SOAP in constants.php

//Returns an array of Products

function browseNodeSearch($browseNode,$page,$mode){

$this->Service="AWSECommerceService";

$this->Operation="ItemSearch";

$this->AWSAccessKeyId=DEVTAG;

$this->AssociateTag=ASSOCIATEID;

$this->BrowseNode=$browseNode;

$this->ResponseGroup="Large";

$this->SearchIndex=$mode;

$this->Sort='salesrank';

$this->TotalPages=$page;

if(METHOD=='SOAP'){

$soapclient=new nusoap_client(

'http://ecs.amazonaws.com/AWSECommerceService/AWSECommerceService.wsdl',

'wsdl');

$soap_proxy=$soapclient->getProxy();

$request=array('Service'=>$this->Service,

'Operation'=>$this->Operation,'BrowseNode'=>$this->BrowseNode,

'ResponseGroup'=>$this->ResponseGroup,'SearchIndex'=>

$this->SearchIndex,'Sort'=>$this->Sort,'TotalPages'=>

$this->TotalPages);

$parameters=array('AWSAccessKeyId'=>DEVTAG,

'AssociateTag'=>ASSOCIATEID,'Request'=>array($request));

//perform actual soap query

$result=$soap_proxy->ItemSearch($parameters);

if(isSOAPError($result)){

return false;

}

$this->totalResults=$result['TotalResults'];

foreach($result['Items']['Item']as$product){

$this->products[]=new Product($product);

}

unset($soapclient);

unset($soap_proxy);

}else{

//form URL and call parseXML to download and parse it

$this->url="http://ecs.amazonaws.com/onca/xml?".

"Service=".$this->Service.

"&Operation=".$this->Operation.

"&AssociateTag=".$this->AssociateTag.

"&AWSAccessKeyId=".$this->AWSAccessKeyId.

"&BrowseNode=".$this->BrowseNode.

"&ResponseGroup=".$this->ResponseGroup.

"&SearchIndex=".$this->SearchIndex.

"&Sort=".$this->Sort.

"&TotalPages=".$this->TotalPages;

$this->parseXML();

}

return$this->products;

}

//Given an ASIN,get the URL of the large image

//Returns a string

function getImageUrlLarge($ASIN,$mode){

foreach($this->products as$product){

if($product->ASIN()==$ASIN){

return$product->imageURLLarge();

}

}

//if not found

$this->ASINSearch($ASIN,$mode);

return$this->products(0)->imageURLLarge();

}

//Perform a query to get a products with specified ASIN

//Switch between XML/HTTP and SOAP in constants.php

//Returns a Products object

function ASINSearch($ASIN,$mode='books'){

$this->type='ASIN';

$this->ASIN=$ASIN;

$this->mode=$mode;

$ASIN=padASIN($ASIN);

$this->Service="AWSECommerceService";

$this->Operation="ItemLookup";

$this->AWSAccessKeyId=DEVTAG;

$this->AssociateTag=ASSOCIATEID;

$this->ResponseGroup="Large";

$this->IdType="ASIN";

$this->ItemId=$ASIN;

if(METHOD=='SOAP'){

$soapclient=new nusoap_client(

'http://ecs.amazonaws.com/AWSECommerceService/AWSECommerceService.wsdl',

'wsdl');

$soap_proxy=$soapclient->getProxy();

$request=array('Service'=>$this->Service,'Operation'=>

$this->Operation,'ResponseGroup'=>$this->ResponseGroup,

'IdType'=>$this->IdType,'ItemId'=>$this->ItemId);

$parameters=array('AWSAccessKeyId'=>DEVTAG,

'AssociateTag'=>ASSOCIATEID,'Request'=>array($request));

//perform actual soap query

$result=$soap_proxy->ItemLookup($parameters);

if(isSOAPError($result)){

return false;

}

$this->products[0]=new Product($result['Items']['Item']);

$this->totalResults=1;

unset($soapclient);unset($soap_proxy);

}else{

//form URL and call parseXML to download and parse it

$this->url="http://ecs.amazonaws.com/onca/xml?".

"Service=".$this->Service.

"&Operation=".$this->Operation.

"&AssociateTag=".$this->AssociateTag.

"&AWSAccessKeyId=".$this->AWSAccessKeyId.

"&ResponseGroup=".$this->ResponseGroup.

"&IdType=".$this->IdType.

"&ItemId=".$this->ItemId;

$this->parseXML();

}

return$this->products[0];

}

//Perform a query to get a page full of products with a keyword search

//Switch between XML/HTTP and SOAP in index.php

//Returns an array of Products

function keywordSearch($search,$page,$mode='Books'){

$this->Service="AWSECommerceService";

$this->Operation="ItemSearch";

$this->AWSAccessKeyId=DEVTAG;

$this->AssociateTag=ASSOCIATEID;

$this->ResponseGroup="Large";

$this->SearchIndex=$mode;

$this->Keywords=$search;

if(METHOD=='SOAP'){

$soapclient=new nusoap_client(

'http://ecs.amazonaws.com/AWSECommerceService/AWSECommerceService.wsdl',

'wsdl');

$soap_proxy=$soapclient->getProxy();

$request=array('Service'=>$this->Service,'Operation'=>

$this->Operation,'ResponseGroup'=>$this->ResponseGroup,

'SearchIndex'=>$this->SearchIndex,'Keywords'=>$this->Keywords);

$parameters=array('AWSAccessKeyId'=>DEVTAG,

'AssociateTag'=>ASSOCIATEID,'Request'=>array($request));

//perform actual soap query

$result=$soap_proxy->ItemSearch($parameters);

if(isSOAPError($result)){

return false;

}

$this->totalResults=$result['TotalResults'];

foreach($result['Items']['Item']as$product){

$this->products[]=new Product($product);

}

unset($soapclient);

unset($soap_proxy);

}else{

$this->url="http://ecs.amazonaws.com/onca/xml?".

"Service=".$this->Service.

"&Operation=".$this->Operation.

"&AssociateTag=".$this->AssociateTag.

"&AWSAccessKeyId=".$this->AWSAccessKeyId.

"&ResponseGroup=".$this->ResponseGroup.

"&SearchIndex=".$this->SearchIndex.

"&Keywords=".$this->Keywords;

$this->parseXML();

}

return$this->products;

}

//Parse the XML into Product object(s)

function parseXML(){

//suppress errors because this will fail sometimes

$xml=@simplexml_load_file($this->url);

if(!$xml){

//try a second time in case just server busy

$xml=@simplexml_load_file($this->url);

if(!$xml){

return false;

}

}

$this->totalResults=(integer)$xml->TotalResults;

foreach($xml->Items->Item as$productXML){

$this->products[]=new Product($productXML);

}

}

}


这个类是非常有用的。它以非常好的黑盒方式封装了与Amazon站点的接口。在这个类中,与Amazon站点的连接可以通过REST方法或SOAP方法来实现。所使用的方法通过在最开始的constants.php文件设置的全局常量METHOD来确定。

下面,让我们回到前面的种类搜索例子。我们按如下方式使用AmazonResultSet:


$ars=new AmazonResultSet;

$ars->browseNodeSearch($parameters['browsenode'],

$parameters['page'],

$parameters['mode']);


这个类没有构造函数,因此我们直接介绍browseNodeSearch()方法。这里,我们将向该方法传递3个参数:我们所感兴趣的browsenode号(相应地,例如,"Business&Investing"或者"Computers&Internet");表示要获得多少记录的页数;以及表示我们所感兴趣的商业类型的模式。该方法的代码如程序清单33-9所示。

程序清单33-9 browseNodeSearch()方法——执行一个种类查询


//Perform a query to get a page full of products from a browse node

//Switch between XML/HTTP and SOAP in constants.php

//Returns an array of Products

function browseNodeSearch($browseNode,$page,$mode){

$this->Service="AWSECommerceService";

$this->Operation="ItemSearch";

$this->AWSAccessKeyId=DEVTAG;

$this->AssociateTag=ASSOCIATEID;

$this->BrowseNode=$browseNode;

$this->ResponseGroup="Large";

$this->SearchIndex=$mode;

$this->Sort="salesrank";

$this->TotalPages=$page;

if(METHOD=='SOAP'){

$soapclient=new nusoap_client(

'http://ecs.amazonaws.com/AWSECommerceService/AWSECommerceService.wsdl',

'wsdl');

$soap_proxy=$soapclient->getProxy();

$request=array('Service'=>$this->Service,

'Operation'=>$this->Operation,'BrowseNode'=>$this->BrowseNode,

'ResponseGroup'=>$this->ResponseGroup,'SearchIndex'=>

$this->SearchIndex,'Sort'=>$this->Sort,'TotalPages'=>

$this->TotalPages);

$parameters=array('AWSAccessKeyId'=>DEVTAG,

'AssociateTag'=>ASSOCIATEID,'Request'=>array($request));

//perform actual soap query

$result=$soap_proxy->ItemSearch($parameters);

if(isSOAPError($result)){

return false;

}

$this->totalResults=$result['TotalResults'];

foreach($result['Items']['Item']as$product){

$this->products[]=new Product($product);

}

unset($soapclient);

unset($soap_proxy);

}else{

//form URL and call parseXML to download and parse it

$this->url="http://ecs.amazonaws.com/onca/xml?".

"Service=".$this->Service.

"&Operation=".$this->Operation.

"&AssociateTag=".$this->AssociateTag.

"&AWSAccessKeyId=".$this->AWSAccessKeyId.

"&BrowseNode=".$this->BrowseNode.

"&ResponseGroup=".$this->ResponseGroup.

"&SearchIndex=".$this->SearchIndex.

"&Sort=".$this->Sort.

"&TotalPages=".$this->TotalPages;

$this->parseXML();

}

return$this->products;

}


根据METHOD常量值的不同,这个方法将执行通过基于SOAP或REST的查询。但是,这两种请求中发送的信息是相同的。如下代码行显示的是请求的变量及其值:


$this->Service="AWSECommerceService";

$this->Operation="ItemSearch";

$this->AWSAccessKeyId=DEVTAG;

$this->AssociateTag=ASSOCIATEID;

$this->BrowseNode=$browseNode;

$this->ResponseGroup="Large";

$this->SearchIndex=$mode;

$this->Sort="salesrank";

$this->TotalPages=$page;


以上代码中的某些变量值是在应用的其他部分设置,例如,$browseNode、$mode和$page的变量值。其他值是常量,例如,DEVTAG和ASSOCIATEID.。而另外一部分的变量$this->Service和$this->Operation以及$this->Sort都是静态变量。

不同的请求类型对变量的要求是不同。以上示例用来浏览根据销售排名的特定节点。查询特定物品和关键字的变量是不同的。在AmazonResultSet.php文件的browseNodeSearch()函数、ASINSearch()函数以及keywordSearch()函数中,你可以找到这些变量的列表。所有请求类型所需变量的详细信息可以在AWS开发人员指南找到。

接下来,我们分别介绍browseNodeSearch()函数中的REST和SOAP查询请求的创建。ASINSearch()函数和keywordSearch()函数的请求创建格式在概念上都是相似的。