Zend_ResutのResultオブジェクト(Zend_Rest_Client_Result)について
Zend_RestでYahoo! オークションやショッピングのapiを使用しました。
<?php define("URL", 'http://auctions.yahooapis.jp/AuctionWebService/V1/Search'); define("APIKEY", '...'); // パラメータ $param = array( 'appid' => APIKEY, 'query' => 'nike', 'type' => 'all', 'category' => 0, 'page' => 1, 'sort' => 'end', 'order' => 'a', ); // クライアントオブジェクト $client = new Zend_Rest_Client(URL); // パラメタを設定 foreach($param as $k=>$v) { $client->{$k}($v); } // リクエスト $res = $client->get(); if($res->isError()) { // エラー処理 } // xmlの処理 ...
必要なパラメータを設定したと思っていたのですが、isError()で毎回falseがでてしまいました。
上記、$resはZend_Rest_Client_Resultオブジェクトです。ダンプしてレスポンスの内容を見ると、商品の情報は正しく取れていました。
Zend_Rest_Client_ResultのisError()のしくみ
Zend_Rest_Client_ResultのisError()の実装を見ると、getStatus()という関数で、リクエストが成功したかどうか判断しています(isSuccess()という関数もありますが、処理は同様です)。
public function getStatus() { $status = $this->_sxml->xpath('//status/text()'); $status = strtolower($status[0]); if (ctype_alpha($status) && $status == 'success') { return true; } elseif (ctype_alpha($status) && $status != 'success') { return false; } else { return (bool) $status; } } public function isError() { $status = $this->getStatus(); if ($status) { return false; } else { return true; } } public function isSuccess() { $status = $this->getStatus(); if ($status) { return true; } else { return false; } }
getStatus()では、XPathで
Yahoo!オークションや、ショッピングapiのレスポンスでは、リクエストに成功しようが失敗しようが、レスポンスに
また、レスポンスコードが400や、500で帰ってくるので、これでチェックすることもできます。
楽天の商品検索apiの場合は、レスポンスに
ただ、先頭が大文字のため、やはりisError()は常にtrueになってしまいます。
レスポンスコードは常に200を返すので、yahooのようにここでは判断できません。
結果的にレスポンスの部分は、各apiごとにまちまちでした。
各ApiごとにZend_Rest_Client_Resultを継承して、getStatus()をオーバーライド、Zend_Rest_ClientにResultオブジェクトを設定したいところです。
任意のレスポンスオブジェクトを設定できるZend_Rest_Client
いまのところ、Zend_Restにそのような仕組みはないので、自作しました。
cleintクラスは、resultオブジェクトを設定するためにプロパティーとメソッドを追加。また、__call()関数内でResultオブジェクトを返す部分を修正。
<?php require_once 'Zend/Rest/Client.php'; require_once 'Zend/Rest/Client/Result.php'; require_once 'Zend/Loader.php'; class Wads_Rest_Client extends Zend_Rest_Client { protected $_resultClass = 'Zend_Rest_Client_Result'; /** * @param string $result * @return Wads_Rest_Client */ public function setResultClass($resultClass) { $this->_resultClass = (string)$resultClass; return $this; } /** * @return string */ public function getResultClass() { return $this->_resultClass; } public function __call($method, $args){ $methods = array('post', 'get', 'delete', 'put'); if (in_array(strtolower($method), $methods)) { if (!isset($args[0])) { $args[0] = $this->_uri->getPath(); } $this->_data['rest'] = 1; $data = array_slice($args, 1) + $this->_data; $response = $this->{'rest' . $method}($args[0], $data); $this->_data = array();//Initializes for next Rest method. Zend_Loader::loadClass($this->_resultClass); return new $this->_resultClass($response->getBody()); } else { // More than one arg means it's definitely a Zend_Rest_Server if (sizeof($args) == 1) { // Uses first called function name as method name if (!isset($this->_data['method'])) { $this->_data['method'] = $method; $this->_data['arg1'] = $args[0]; } $this->_data[$method] = $args[0]; } else { $this->_data['method'] = $method; if (sizeof($args) > 0) { foreach ($args as $key => $arg) { $key = 'arg' . $key; $this->_data[$key] = $arg; } } } return $this; } } }
Yahoo api全般で使用できるresultクラス
<?php require_once 'Zend/Rest/Client/Result.php'; class Wads_Rest_Client_Result_Yahoo extends Zend_Rest_Client_Result { public function getStatus() { return !(bool)$this->_sxml->xpath('//Message/text()'); } }
<?php require_once 'Zend/Rest/Client/Result.php'; class Wads_Rest_Client_Result_Rakuten extends Zend_Rest_Client_Result { public function getStatus() { $status = $this->_sxml->xpath('//Status/text()'); $status = strtolower($status[0]); if (ctype_alpha($status) && $status == 'success') { return true; } elseif (ctype_alpha($status) && $status != 'success') { return false; } else { return (bool) $status; } } }
で、実際に使用するときは、以下のようになります
$client = new Wads_Rest_Client(URL); // resultクラスを設定 $client->setResultClass('Wads_Rest_Client_Result_Yahoo'); // 楽天の場合 //$client->setResultClass('Wads_Rest_Client_Result_Rakuten'); foreach($param as $k=>$v) { $client->{$k}($v); } $res = $client->get(); if($res->isError()) { // エラー処理 } // xmlの処理 ...
これがいい方法なのかどうかはわかりませんが、当面はこれで運用してみます。