商品検索がエラーの時に再試行することで、キーワードによる商品検索をして、「アマゾン商品の検索結果」を取得する
「アマゾン商品の検索結果」を取得する時に、エラーが発生した場合、再試行する処理について、PHPソースコードを解説しています。
for文のループ処理によって、指定された回数、再試行の処理を行います。
再試行を行なって正常に処理できた場合、「アマゾン商品の検索結果」を取得します。
再試行を行なっても、正常に「アマゾン商品の検索結果」を取得できなかった場合は、エラーを通知します。
商品検索がエラーの時に再試行することで、キーワードによる商品検索をして、「アマゾン商品の検索結果」を取得する
$lastHttpRequestException;
for($i = 0; $i < $retryCount; $i ++) { // 例:リトライ回数:2回 //TODO 設定画面で指定する
if ($i >= 1) {
sleep ( 1 ); // 再試行の待ち時間(1秒)
}
try {
/*
* ここでSDKあり・なしの分岐処理をするかもしれない。
* SDKAmazonRequest::requestSearchIndex()
*/
$searchItemsResponse = SearchIndexRequest::request ( $partnerTag, $keyword, $searchIndex, $resources, $hostname, $accessKey, $secretKey, $regionName );
return $searchItemsResponse;
} catch ( HttpRequestException $ex ) {
$lastHttpRequestException = $ex;
}
}
throw $lastHttpRequestException;
上記のソースコードでは、SearchIndexRequest::request()関数によって、「アマゾン商品の検索結果」を取得します。
「アマゾン商品の検索結果」を取得する時に、エラーが起きた場合、再試行します。
for文のループ処理によって、再試行の処理を行う
for($i = 0; $i < $retryCount; $i ++)
「アマゾン商品の検索結果」を取得する時にエラーが起きた場合、
上記のfor文によって、指定された回数だけ、「アマゾン商品の検索結果」を取得する処理を再試行します。
再試行する回数は、$retryCount変数の値です。
細かく言うと、再試行する回数は($retryCount変数の値 - 1 )です。
for文のループ処理の1回目は、再試行ではないからです。
再試行の処理を行う場合は、1秒間待ってから行う
if ($i >= 1) {
sleep ( 1 ); // 再試行の待ち時間(1秒)
}
1回以上の再試行を行う場合は、1秒間待ってから行います。
上記ソースコードのsleep()関数によって、1秒間待ってから処理を続けます。
PHPのsleep()関数は、指定された秒数の間、現在のPHPスクリプトの実行を遅らせるために使用されます。
「アマゾン商品の検索結果」を取得する処理を、1秒間待ってから再開する理由は、
Amazon Product Advertising APIを、短時間に連続して呼び出さないようにするためです。
API呼び出しでエラーが起きても、
1秒後なら、API呼び出しが正常に終了するかもしれない、と期待しています。
Amazon Product Advertising API には、短時間に実行できるリクエストの数に制限があります。
リクエストが多すぎる場合、API はエラー メッセージ「TooManyRequests」を返します。
sleep()関数によって、1秒間待ってからAPIをリクエストすることで、エラー発生を防ぐことを試みます。
再試行してエラーが起きた場合、最後に起きたエラーを通知する
$lastHttpRequestException;
for($i = 0; $i < $retryCount; $i ++) { // 例:リトライ回数:2回 //TODO 設定画面で指定する
中略
try {
$searchItemsResponse = SearchIndexRequest::request ( $partnerTag, $keyword, $searchIndex, $resources, $hostname, $accessKey, $secretKey, $regionName );
return $searchItemsResponse;
} catch ( HttpRequestException $ex ) {
$lastHttpRequestException = $ex;
}
}
throw $lastHttpRequestException;
SearchIndexRequest::request()関数の処理が正常に終了した場合、
「アマゾン商品の検索結果」が$searchItemsResponse変数に代入されます。
そしてreturn文によって、$searchItemsResponse変数が保持する「アマゾン商品の検索結果」が返されます。
return文が実行されることで、再試行の処理を行うfor文のループ処理が終了します。
SearchIndexRequest::request()関数の処理で、HTTPリクエスト関連のエラーが起きた場合、
catch文の処理が実行されます。
$lastHttpRequestException変数に、$ex変数が保持する「HTTPリクエスト例外の内容」が代入されます。
例外の内容が代入されることより、最後に発生したエラー情報を保持することになります。
それ以前に発生したエラー情報は、代入することにより上書きされます。
指定された回数($retryCount変数の値 - 1 )だけ再試行を行なっても、エラーが発生し続けた場合、
for文のループを終了後、最後に発生したHTTPリクエスト例外が、throw文によって通知されます。
最後に発生した例外ということを示したいから、lastという英単語を使いました
$lastHttpRequestException変数については、
最後に発生した例外だけを保持している、ということを示そうと思いました。
なので、lastという英単語を使ってみました。
例えば、再試行を3回実行して、1回目から3回目までのすべての再試行でエラーが起きた場合、
$lastHttpRequestException変数は、3回目に発生した例外だけを保持しています。
lastという英単語を使うことで、上記の説明内容を表現したかったです。
だけど、他のプログラマーに対して上記の説明内容が伝わったかどうかは、わかりません。
コメント文をなるべく書かないソースコードを、目指しました
プログラムのソースコードでは、
- コメント文をなるべく書かない。
- 英語文のようなソースコードで、プログラム処理の内容を表したい。
そんなことを目指してソースコードを書いたのですが、かなり難しいです。
ちなみに、コメント文をなるべく書きたくないのは、コメント文の内容がソースコードの内容と違う状態になったりするからです。
仕様変更などでソースコードを修正した際、コメント文の内容を修正し忘れることがあります。
古い仕様を表しているコメント文は、他のプログラマーを迷わせることになります。
コメント文とソースコード、どっちが正しいか?迷います。
キーワードによる商品検索をして、「アマゾン商品の検索結果」を取得するのに必要な各情報を、用意する
public static function requestSearchIndex(URLInfo $urlInfo, CommonRESTParameter $commonParameter, RESTParameter $restParameter, int $itemCount, $retryCount = 1) {
中略
$partnerTag = $commonParameter->getAssociateTag ();
$keyword = $restParameter->getKeyword ();
$searchIndex = $restParameter->getSearchIndex ();
$resources = $restParameter->getSearchItemsResources ();
$hostname = $urlInfo->getHostname ();
$accessKey = $commonParameter->getAccessKey ();
$secretKey = $commonParameter->getSecretKey ();
$regionName = $commonParameter->getRegion ();
以下省略
$searchItemsResponse = SearchIndexRequest::request ( $partnerTag, $keyword, $searchIndex, $resources, $hostname, $accessKey, $secretKey, $regionName );
以下省略
SearchIndexRequest::request()関数は、
Amazon Product Advertising APIを使って、キーワードで商品検索して、「アマゾン商品の検索結果」を取得します。
この関数を実行するために、以下の情報を用意します。
- Product Advertising API ホスト($hostname変数)
- Product Advertising API アクセスキー($accessKey変数)
- Product Advertising API アソシエイトタグ($partnerTag変数)
- Product Advertising API シークレットキー($secretKey変数)
- Product Advertising API リージョン($regionName変数)
- SearchItems の Resources Parameter($resources変数)
これらの情報は、「アマゾンの設定」で設定します。
※関連記事:アフィリエイト商品表示・WordPressプラグイン、アフィリエイトの設定、アマゾンの設定。
なお、アソシエイトタグの変数名が$partnerTagになっているのは、参考にしたAmazon Product Advertising APIのサンプルコードにおいて、$partnerTagと書かれていたためです。
SearchIndexRequest::request()関数を実行するために、さらに以下の情報を用意します。
- SearchItemsオペレーションの検索インデックス($searchIndex変数)
- 商品検索で使うキーワード($keyword変数)
これらの情報は、当プラグインのショートコードの属性で設定します。
※関連記事:アフィリエイト商品表示・WordPressプラグイン、ショートコードの属性
「表示する商品数」が0件の場合、「アマゾン商品の検索結果」が存在しないことを示すNULL値を、return文で返す
public static function requestSearchIndex(URLInfo $urlInfo, CommonRESTParameter $commonParameter, RESTParameter $restParameter, int $itemCount, $retryCount = 1) {
if ($itemCount <= 0) {
return NULL; // 表示する件数が0件なので、商品情報なしとする。
}
以下省略
当プラグインのショートコードにおいて、「表示する商品数」属性の値が0の場合、
$itemCount変数の値は、0になります。
※関連記事:アフィリエイト商品表示・WordPressプラグイン、ショートコードの属性
「表示する商品数」が0件なので、アマゾンの「アフィリエイト商品のHTML」を表示しません。
つまり、「アマゾン商品の検索結果」を取得しなくて良いです。
よって、「アマゾン商品の検索結果」が存在しないことを示すNULL値を、return文で返します。
AmazonRequest.phpのソースコード
<?php
namespace goodsmemo\amazon;
use goodsmemo\amazon\CommonRESTParameter;
use goodsmemo\amazon\RESTParameter;
use goodsmemo\amazon\withoutsdk\SearchIndexRequest;
use goodsmemo\network\URLInfo;
use goodsmemo\exception\HttpRequestException;
require_once GOODS_MEMO_DIR . "amazon/CommonRESTParameter.php";
require_once GOODS_MEMO_DIR . "amazon/RESTParameter.php";
require_once GOODS_MEMO_DIR . "amazon/withoutsdk/SearchIndexRequest.php";
require_once GOODS_MEMO_DIR . "network/URLInfo.php";
require_once GOODS_MEMO_DIR . "exception/HttpRequestException.php";
class AmazonRequest {
public static function requestSearchIndex(URLInfo $urlInfo, CommonRESTParameter $commonParameter, RESTParameter $restParameter, int $itemCount, $retryCount = 1) {
if ($itemCount <= 0) {
return NULL; // 表示する件数が0件なので、商品情報なしとする。
}
$partnerTag = $commonParameter->getAssociateTag ();
$keyword = $restParameter->getKeyword ();
$searchIndex = $restParameter->getSearchIndex ();
$resources = $restParameter->getSearchItemsResources ();
$hostname = $urlInfo->getHostname ();
$accessKey = $commonParameter->getAccessKey ();
$secretKey = $commonParameter->getSecretKey ();
$regionName = $commonParameter->getRegion ();
$lastHttpRequestException;
for($i = 0; $i < $retryCount; $i ++) { // 例:リトライ回数:2回 //TODO 設定画面で指定する
if ($i >= 1) {
sleep ( 1 ); // 再試行の待ち時間(1秒)
}
try {
/*
* ここでSDKあり・なしの分岐処理をするかもしれない。
* SDKAmazonRequest::requestSearchIndex()
*/
$searchItemsResponse = SearchIndexRequest::request ( $partnerTag, $keyword, $searchIndex, $resources, $hostname, $accessKey, $secretKey, $regionName );
return $searchItemsResponse;
} catch ( HttpRequestException $ex ) {
$lastHttpRequestException = $ex;
}
}
throw $lastHttpRequestException;
}
}