
CakePHPで楽天APIを叩いてみる(3)コントローラー編
2019/03/04
ではCakePHPで楽天APIの3回目、コントローラー編です。
コントローラーでモデル及びコンポーネントを呼び出し、結果を取得するという流れです。
ページ送りに関する設定も行います。
ではコントローラー内容です。
app/controllers/products_controller.php
[php]
<?php
App::import('Sanitize');
App::import('Vendor', 'include_path_vendors');
App::import('Vendor', 'Pager', array('file' => 'Pager-2.4.8' . DS . 'Pager.php'));
class ProductsController extends AppController
{
// ヘルパー宣言
var $helpers = array('Html', 'Form', 'Time', 'Text', 'DateFormat');
// モデル宣言
var $uses = array('Product');
// コンポーネント宣言
var $components = array('string', 'RakutenApi');
/**
* <楽天> 商品一覧
*
*/
function productlist()
{
//------------------------------------------------------------
// 検索条件
//------------------------------------------------------------
// 数字版「並び替え」条件配列を ProductModel より取得
$sort_option_array = $this->Product->sort_option_array;
$this->set('sort_option_array', $sort_option_array);
// 文字版「並び替え」条件配列を ProductModel より取得
$sort_option_str_array = $this->Product->sort_option_str_array;
// 表示数を AppModel より取得
$list_limit = $this->Product->list_limit;
//------------------------------------------------------------
// 検索オプション、文字列等の調整
//------------------------------------------------------------
// ジャンルコード検索用
if( !empty($this->params['url']['genre_id']) )
{
$genre_id = Sanitize::clean($this->params['url']['genre_id']);
}
else
{
if(!empty($this->passedArgs['genre_id']))
{
$genre_id = Sanitize::clean($this->passedArgs['genre_id']);
}
else
{
$genre_id = "0";
}
}
// ページ
if( !empty($this->params['url']['page']) )
{
$page = Sanitize::clean($this->params['url']['page']);
}
else
{
if(!empty($this->passedArgs['page']))
{
$page = Sanitize::clean($this->passedArgs['page']);
}
else
{
$page = "1";
}
}
// 並び替え(ソート)
if( !empty($this->params['url']['sort']) )
{
$sort = Sanitize::clean($this->params['url']['sort']);
}
else
{
if(!empty($this->passedArgs['sort']))
{
$sort = Sanitize::clean($this->passedArgs['sort']);
}
else
{
$sort = 1;
}
}
// フリーワード検索用
if( !empty($this->params['url']['keyword']) )
{
$gKeyword = $this->params['url']['keyword'];
// 文字コード調査
$enc = mb_detect_encoding($gKeyword, 'SJIS,UTF-8');
if( $enc != Configure::read('App.encoding') )
{
// UTF-8に変換
$this->params['url']['keyword'] = mb_convert_encoding($gKeyword, Configure::read('App.encoding'));
}
// stringコンポーネントで全角変換する
$this->params['url']['keyword'] = $this->string->to_zen_katakana($this->params['url']['keyword']);
}
if( !empty($this->params['url']['keyword']) )
{
$keyword = Sanitize::clean($this->params['url']['keyword']);
}
else
{
if(!empty($this->passedArgs['keyword']))
{
$keyword = Sanitize::clean($this->passedArgs['keyword']);
}
else
{
$keyword = "";
}
}
// 検索キーワード
$keyword_encoded = "";
if( !empty($keyword) )
{
//「全角スペース」を「半角スペース」に変換
$keyword_encoded = mb_ereg_replace(' ', ' ', $keyword);
}
// 一覧件数
if( !empty($this->params['url']['get_list_limit']) )
{
$get_list_limit = Sanitize::clean($this->params['url']['get_list_limit']);
if( array_key_exists($get_list_limit, $list_limit) == FALSE )
{
$get_list_limit = SEARCH_RESULT_LIST_LIMIT;
}
}
else
{
if( !empty($this->passedArgs['get_list_limit']) )
{
$get_list_limit = Sanitize::clean($this->passedArgs['get_list_limit']);
if( array_key_exists($get_list_limit, $list_limit) == FALSE )
{
$get_list_limit = SEARCH_RESULT_LIST_LIMIT;
}
}
else
{
$get_list_limit = SEARCH_RESULT_LIST_LIMIT;
}
}
//------------------------------------------------------------
// 検索条件まとめ
//------------------------------------------------------------
$conditions = array(
'genreId' => $genre_id,
'hits' => $get_list_limit,
'page' => $page,
);
// 検索ワードの指定がない場合、$conditionsに "keyword" があるとエラーになるので、ある場合だけ条件とする
if( !empty($keyword_encoded) )
{
$conditions["keyword"] = $keyword_encoded;
}
// 並び順
if( !empty($sort) )
{
if( $sort == 2 )
{
$sort_option_str_array["$sort"] = '+' . $sort_option_str_array["$sort"];
}
$conditions["sort"] = $sort_option_str_array["$sort"];
}
//------------------------------------------------------------
// コンポーネント化している楽天商品検索を実行
//------------------------------------------------------------
$item_ret = $this->RakutenApi->raku_item_search( $conditions );
// 2次元配列なのでバラす
extract($item_ret);
// ビューにセット
$this->set('item_status', $ret_status);
$this->set('item_search', $ret_item);
$this->set('count', $ret_item["count"]);
$this->set('keyword', $keyword_encoded);
$this->set('genre_id', $genre_id);
$this->set('sort', $sort_option_str_array["$sort"]);
//------------------------------------------------------------
// ページング処理
//------------------------------------------------------------
// pathパラメータ
$option_path = 'genre_id:' . $genre_id;
if( !empty($keyword_encoded) )
{
$option_path .= '/keyword:' . $keyword_encoded;
}
if( !empty($sort) )
{
$option_path .= '/sort:' . $sort;
}
// 表示数
$option_path .= '/get_list_limit:' . $get_list_limit;
if( $ret_item["count"] >= SEARCH_RESULT_LIST_LIMIT * 100 )
{
// ページ送りを100がリミットとする
$total_item_count = SEARCH_RESULT_LIST_LIMIT * 100;
}
else
{
// 100以下の場合
$total_item_count = $ret_item["count"];
}
// Pager用パラメータ
$p_options = array(
'totalItems' => $total_item_count,
'perPage' => SEARCH_RESULT_LIST_LIMIT,
'urlVar' => "page",
'path' => FULL_BASE_URL . '/raku/products/productlist/' . $option_path,
'append' => false,
'fileName' => "page:%d",
'currentPage' => $page,
'mode' => "Jumping",
'delta' => "8",
'separator' => "",
'spacesBeforeSeparator' => "",
'spacesAfterSeparator' => "",
'prevImg' => '<<',
'nextImg' => '>>',
'curPageLinkClassName' => "current",
);
$pager =& Pager::factory($p_options);
$navi = $pager->getLinks();
$this->set('navi', $navi["all"]);
//--------------------------------------------------
// HTMLヘッダ内処理
//--------------------------------------------------
if( !empty($keyword_encoded) )
{
// titleタグ
$this->set('title_for_layout', '[' . SYSTEM_NAME_FRONT . '] 商品一覧 | ' . $keyword_encoded . ' | ' . $page . 'ページ');
// metaタグ内のdescription
$this->set('description_for_layout', '検索ワード ' . $keyword_encoded . ' の商品一覧ページ ' . $page . ' ページ目です');
// metaタグ内のkeyword
$this->set('keyword_for_layout', '');
}
else
{
$this->set('title_for_layout', '[' . SYSTEM_NAME_FRONT . '] 商品一覧 | ' . $Current['genreName'] . ' | ' . $page . 'ページ');
$this->set('description_for_layout', 'ジャンル ' . $Current['genreName'] . ' 内の商品一覧ページ ' . $page . ' ページ目です');
$this->set('keyword_for_layout', '');
}
}
?>
[/php]
では、解説。
3、4行目で、前回設置作成した、Pagerライブラリとインクルードパスを呼び出します。
21行目から、productlist アクションを作っていきます。
23?31行目で、モデルに設定したソート順を取得します。
34行目のAppModelに設定している内容は以下となりますが、もちろんこの内容は、productモデルに書いても問題ありません。
[php]
/**
* 一覧件数
*
*/
var $list_limit = array(
"2" => "2件",
"3" => "3件",
"5" => "5件",
"6" => "6件",
"9" => "9件",
"10" => "10件",
"20" => "20件",
"50" => "50件",
"100" => "100件",
);
[/php]
36?155行で、GETで取得する各オプションのサニタイズと置き換えを行います。
前回書いたURLのサンプルを見れば分かりますが、/keyword:きーわーど/sort:1/ のようなURLとするので、
基本的に $this->passedArgs で取得したものに対して行えば問題無いと思います。
デフォルトの表示件数である SEARCH_RESULT_LIST_LIMIT には、app.php にて「9」件と設定しています。
160?181行目で、取得したオプション(条件)を配列にまとめます。
ソート順指定が2(itemPrice)の場合は、「+itemPrice」とするために、「+」を追加します。
186行目で、オプションを引数にコンポーネント化済APIを作動させます。
返り値の $item_ret を extract で分解し、必要な変数/配列をビューにセット。
202行目からはページ送り用の設定です。
ページ番号をクリックした際に送られるURLのpathパラメータを設定。
パラメータには genre_id、keyword、sort、get_list_limitを指定します。
218行目からは、取得するアイテム数がやたらとある場合に備えて、最大ページ数を100ページとする処理を行います。
230行目から、PEAR Pager用設定を行います。
以下の様な内容です。
totalItems:対象となるアイテム数(itemDataが未指定の場合に使用)
perPage:1ページごとに表示されるアイテム数
urlVar:ページ番号を示すためのクエリ変数名(デフォルトは「pageID」)
path:ページへの絶対パス(ページ名は除く)
append:TRUEならpageIDはクエリ文字列としてURLに追加。FALSEならfileNameに従ってURLに埋め込まれる(デフォルトは「TRUE」)
fileName:ページ名。appendがTRUEなら"%d"
currentPage:初期ページ番号
mode:動作モードを指定。ジャンプ型(Jumping)又はスライド型(Sliding)
delta:現在のページの前後に表示するページ番号の数
separator:ページ番号を分けるための区切り文字。カンマやハイフンの他にタグも可能
spacesBeforeSeparator:区切り文字の前のスペース数
spacesAfterSeparator:区切り文字の後のスペース数
prevImg:前のページのリンクである「<<」の代替文字。タグも可能
nextImg:のページのリンクである「&lgt;>」の代替文字。タグも可能
curPageLinkClassName:現在のページのリンクのスタイルのためのCSSクラス
248行目でインスタンス化、249行目の getLinksメソッドで「連想配列として戻る/次/最初/最後のリンクとページリンク」を取得し、ビューにセットします。
255行目以降は、HTMLタイトルの設定処理です。SEOに考慮して作成しましたが、成果の方は疑わしいので、無視していただいて構いません。
駆け足でしたが、コントローラーは以上です。
ページ送り処理にちょっと頭を捻りましたが、その他は目新しい処理もなく、CakePHPerでしたら一目瞭然だと思います。
[tgAmazonItemLookup asin="4798033146" related="1"]