お世話になります。
以前(http://q.hatena.ne.jp/1375374890)色々教えていただき、検索結果は取得できたのですが、これをページングさせたく、再度質問させて頂きます。
<?php
~前略(前回と同じ)~
$yahoo_data = array();
foreach ($yxml->Result->Hit as $Hit) {
$yahoo_data[] = array('itemName'=>(string)$Hit->Name,
//~中略~
'yitemCount'=>(string)$totalResultsAvailable);
}
$merge_data = array_merge($rakuten_data,$yahoo_data);
//~中略(教えて頂いたソート方法)~
foreach(array_slice($merge_data,0,21) as $result) {
?>
<?=mb_substr($result[$itemName],0,25,'UTF-8')?>
//~中略~
<?php } ?>
この後にページング処理を入れたく、以下などを参考にしたのですがうまくいきません。
http://tenderfeel.xsrv.jp/php/639/
http://rasukaru55.sitemix.jp/pageing.php
検索結果の数を取得できないと話にならないと思い、
$totalResultsAvailable = $yxml->attributes()->totalResultsAvailable;
……
'yitemCount'=>(string)$totalResultsAvailable);
を入れることでヤフーの検索結果数は取得できたのですが、楽天はできていません。
できれば楽天の取得方法、又はページングの方法だけでもご教授いただけませんでしょうか。
文字数の関係で中略が多く恐縮です。
$merge_dataにはソート済みの結果が格納されているのですよね?
例えば1ページ当たり30件のデータを表示する場合は、
nページ目の時には30*(n-1)から30件分取り出せばいいので、
では
<?php //ページ番号取得。ないときには1ページ目を表示。 $page=1; if(isset($_GET['page'])){ $page=$_GET['page']); } //1件当たりの表示件数。30だと1ページにつき30件表示します。 $echo_num=30; $start_num=$echo_num*($page-1); : foreach(array_slice($merge_data,$start_num,$echo_num) as $result) { ?> <?=mb_substr($result[$itemName],0,25,'UTF-8')?> //~中略~ <?php } ?>
でいいと思います。
30件ずつ表示する設定で1ページ目を表示してみると、
$start_num=0;$echo_num=30;となり、このとき
array_slice($merge_data,$start_num,$echo_num)
は
array_slice($merge_data,0,30)
と同値になります。
ご回答いただきありがとうございました。
結果的には、まだ処理できていないため、もう少し考えてみようと思います。
ありがとうございました。
「count」に検索結果の総商品数が入っているようです。
http://webservice.rakuten.co.jp/api/ichibaitemsearch/
$xml->Body->ItemSearch->count
または
$xml->Body->ItemSearch->Items->count
で取得しようとしたのですが、できなかったため途方に暮れております…
header("Content-Type:text/plain;charset=UTF-8");
$root = simplexml_load_file($file,'SimpleXMLElement',LIBXML_NOWARNING);
print $root->Body->children('itemSearch',true)->ItemSearch->children("")->count;
しかし、ページングはやはりできていません。。。
1ページ目のデータをそれぞれ何件分取得しているのでしょう?
http://q.hatena.ne.jp/1375374890
----------------------------------------------------------------------
■やりたいこと
楽天とYahooショッピングの商品検索APIの結果を混ぜ、条件でソートした30件を表示。
----------------------------------------------------------------------
Yahoo!ショッピングの商品検索APIで1回に取得できるのは20~50件です。
http://developer.yahoo.co.jp/webapi/shopping/shopping/v1/itemsearch.html
----------------------------------------------------------------------
hits integer
(デフォルト:20) 取得する検索結果数。デフォルトは20、最大値は50。
----------------------------------------------------------------------
楽天商品検索APIで1回に取得できるのは1~30件です。
----------------------------------------------------------------------
1ページあたりの取得件数 hits int - 30 1から30までの整数
----------------------------------------------------------------------
双方からそれぞれ15件ずつ取得した合計の30件をソートして表示するのでしたら可能だと思いますが、価格(?)など何らかの条件でのソートした結果を正確に30件ずつ表示したい場合は、かなり難しくなると思います。
前回の質問を見る限り、結合後のデータから上位30件分を抜き出して表示しているようですので、前記の後者に該当すると思います。
場合によってはページング処理は諦める必要があると思います。
ありがとうございます。
仰るとおり、双方の結果をソートして、上限を決めることなく表示させてページングさせようとしております。
やはりかなり難しいんですね。。
ありがとうございます。
もう少し自分の中でも噛み砕いてみたいと思います。
ポイントを差し上げたいのですが、コメントにはできないんでしょうか。
とにかく、ありがとうございました。
ページング処理をする場合
1:ある程度の商品点数を取り込んで自分でページング処理をする方法です。が多くの商品点数を取り込むと時間もかかりますし、それほど多くのページも閲覧されとは思われないので処理の割に効果が見込めないと思います。また多くの商品点数を毎回取り込むと無駄ですからキャッシュも必要かもしれません。
2:ページ単位で商品点数を取り込む方法です。ソートの整合性は多少失われますがこれまでの処理の流れが使えます。
2のやりかたで説明します。
データを取り込む際にpageとhitsを指定できるようにします。またソートされた結果を取り込む必要があるのでsortも指定できるようにする必要があります。
function pagingはhttp://tenderfeel.xsrv.jp/php/639/のものを使うものとします。
パラメータとしてqueryとpageの二つが必要になります。
index.php?query=vaio vaioを商品検索して1ページ目を表示します。(最初にアクセスする必要があります。)
index.php?page=n 以前のqueryでnページ目を表示します。
本来はindex.php?query=vaio&page=nとなったほうが簡単なのですがpageingを変更しないといけないのでsessionを使ってqueryの値を保存するという方法をとっています。
sort項目として幾つかありますが共通するのはこの三つのようです。
itemPrice | price
reviewCount | review_count
affiliateRat | affiliate
前回はsortでグローバル変数を使って値を引き渡していたのですがPHP5.3から無名関数で設定済みの変数の値を引き継ぐuseというものが使えるようです。
こちらの方が多少スマートのように思います。
define ('RAKUTEN_SHOP','https://app.rakuten.co.jp/services/api/IchibaItem/Search/20130805?applicationId=??');
define ('YAHOO_SHOP','http://shopping.yahooapis.jp/ShoppingWebService/V1/itemSearch?appid=??');
// defineのRAKUTEN_SHOPとYAHOO_SHOPはアプリケーションIDやアフィリエイトID、その他などを付加あるいは変更する必要があります。
// 楽天はバージョンによってurlが異なります。それによってxmlへのアクセス方法が異なるかもしれません。このコードでは20130805のものです。
function rakuten_shop_api($query, $page, $hits, $s, $o='%2b') {
$sort_key = array('ItemPrice'=>'itemPrice','ReviewCount'=>'reviewCount','affiliateRat'=>'affiliateRat');
$url = RAKUTEN_SHOP.'&keyword='.urlencode($query).'&page='.$page.'&hits='.$hits.'&sort='.$o.$sort_key[$s];
echo $url."<br>\n";
$data = file_get_contents($url);
return simplexml_load_string($data);
}
function yahoo_shop_api($query, $page, $hits, $s, $o='%2b') {
$sort_key = array('ItemPrice'=>'price','ReviewCount'=>'review_count','affiliateRat'=>'affiliate');
$offset = ($page-1)*$hits;
$url = YAHOO_SHOP.'&query='.urlencode($query).'&offset='.$offset.'&hits='.$hits.'&sort='.$o.$sort_key[$s];
echo 'yahoo='.$url."<br>\n";
return simplexml_load_string(file_get_contents($url));
}
session_start();
if (!isset($_SESSION["cafe"]))
$_SESSION["cafe"] = array('',1,15,'ItemPrice'); // 最初のsessionでは初期値を設定します。
list($query, $limit, $hits, $sort) = $_SESSION["cafe"];
// sessionを使って$query, $limit, $hits, $sortの変数の値を引き継ぎます。
if (isset($_GET["query"])) $query = $_GET["query"];
$page = empty($_GET["page"]) ? 1 : intval($_GET["page"]); //ページ番号
if ($page > $limit) $page = $limit; // limitの取扱いはあまり上手くありません。
$xml = rakuten_shop_api($query, $page, $hits, $sort);
# var_dump($xml);
$data = array();
foreach ($xml->Items->Item as $item) {
$data[] = array('ItemName'=>(string)$item->itemName,
'ItemPrice'=>(string)$item->itemPrice,
'smallImageUrl'=>(string)$item->smallImageUrls->imageUrl,
'affiliateUrl'=>(string)$item->affiliateUrl,
'affiliateRat'=>(string)$item->affiliateRat,
'ItemCaption'=>(string)$item->itemCaption,
'ReviewCount'=>(string)$item->reviewCount);
} // 楽天のデータを取り込み$dataに格納します。
# var_dump($yxml);
$yxml = yahoo_shop_api($query, $page, $hits, $sort);
foreach ($yxml->Result->Hit as $Hit) {
$data[] = array('ItemName'=>(string)$Hit->Name,
'ItemPrice'=>(string)$Hit->Price,
'smallImageUrl'=>(string)$Hit->Image->Small,
'affiliateUrl'=>'',
'affiliateRat'=>(string)$Hit->Affiliate->Rate,
'ItemCaption'=>(string)$Hit->Description,
'ReviewCount'=>(string)$Hit->Review->Count);
}} // Yahooのデータを取り込み同じく$dataに格納します。そうすることでarray_mergeする必要が無くなりました。
if (isset($_GET["query"])) $limit = floor(($xml->count + $yxml->attributes()->totalResultsAvailable + $hits - 1)/$hits);
echo 'count='.$xml->count."<br>\n";
echo 'totalResultsAvailable='.$yxml->attributes()->totalResultsAvailable."<br>\n";
echo 'limit='.$limit."<br>\n";
$_SESSION["cafe"] = array($query, $limit, $hits, $sort); // 現在の値を次回に引き継ぐためセッション変数に格納します。
usort($data, function ($a, $b) use ($sort) {
return ($a["$sort"] == $b["$sort"]) ? 0 :
(($a["$sort"] < $b["$sort"]) ? -1 : 1);
});
foreach($data as $result) {
echo mb_substr($result["ItemName"],0,25,'UTF-8').' '.$result["ItemPrice"]."円<br>";
echo '<a href="'.$result["affiliateUrl"].'" target="blank"><img src="'.$result["smallImageUrl"].'"></a>';
echo $result["ItemCaption"].'<br><br>';
}
paging($limit, $page, 10);
度々ありがとうございます。
格が違うというか、自分にはとても思いつかない、思いつくとも思えない内容です。
本当に感謝申し上げます。
こちらを参考に、今一度構築してみます。
できればポイントを差し上げたいのですが、できないようなので、カラースターというのを付けさせていただきました(これに価値があるのか、わからないのですが……)
また何かありましたら、是非よろしくお願い致します。
度々申し訳ありません。
usort($data, function ($a, $b) use ($sort) {
return ($a["$sort"] == $b["$sort"]) ? 0 :
(($a["$sort"] < $b["$sort"]) ? -1 : 1);
});
の部分でエラーが出るようなのですが、原因などお分かりになるでしょうか。
以前のcmp_funcで書き換えて下さい。
ただ名前を$SORT_fieldから$sortと名前を変えたので書き換える必要があります。
function cmp_func($a, $b)
{
global $sort;
$field = $sort;
if ($a[$field] == $b[$field]) {
return 0;
}
return ($a[$field] < $b[$field]) ? -1 : 1;
}
とりあえず動作を確認するだけならusortしなくてもいいです。
usortについては昇順、降順に対応するために今後も変更が必要になる部分です。
これで色々試させていただきます。