質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

PHPと楽天APIを使って、2つの商品の最安値ランキングから、ショップが重複するものをさらにランキングに

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,614

miyaya

score 6

前提・実現したいこと

PHPの勉強で、楽天APIを引っ張って、最安値ランキングを作っています。
商品ごとのランキングはできたんですが、
次に作りたいのが、2つ商品のランキングを比較し、
両者で重複するショップを取得し、
2つの商品の金額を足して、安い順に並び直したいと思っています。

例:「2種類の猫のフードを、両方売っているショップで、なおかつ最安値で買いたい」

※下記のソースコードには、楽天APIのapplicationIdが入っていないので、
そのままでは動かないことをご了承下さい。

2つの商品を選択するHTMLソースコード

<form action="kotae.php" name="form1" method="post">
        <select name="food1">
        <option value="センシブル,4kg">センシブル 4kg</option>
        <option value="センシブル,2kg">センシブル 2kg</option>
        </select>

        <select name="food2">
        <option value="メールケア,4kg">メールケア 4kg</option>
        <option value="メールケア,2kg">メールケア 2kg</option>
        </select>

        <input type="submit" value="計算する"></p>
</form>

ボタンを押した先「kotae.php」のソースコード

<?php 
$food1 = $_POST['food1']; //1つ目のselectのoptionのvalue
$food2 = $_POST['food2']; //2つ目のselectのoptionのvalue

//カンマで分けて配列にする
$food1 = explode(',',$food1);
$food2 = explode(',',$food2);

//NGキーワード(他のグラム数の商品が混ざらないように)
if( $food1[1] == '4kg' ){
  $NGkeyword = '0.2kg 0.4kg 400g 2kg';
} elseif( $food1[1] == '2kg' ){
  $NGkeyword = '0.2kg 0.4kg 400g 4kg';
} elseif( $food1[1] == '400g' ){
  $NGkeyword = '0.2kg 2kg 4kg';
}elseif( $food1[1] == '200g' ){
  $NGkeyword = '400g 0.4kg 2kg 4kg';
}

//エンコード
$NGkeyword = mb_convert_encoding($NGkeyword,'UTF-8','auto');
$NGkeyword = urlencode($NGkeyword);

 //1個目の商品エンコード
$food1_en1 = mb_convert_encoding($food1[0],'UTF-8','auto');
$food1_en2 = mb_convert_encoding($food1[1],'UTF-8','auto');
$food1_en1 = urlencode($food1_en1);
$food1_en2 = urlencode($food1_en2);

 //2個目の商品エンコード
$food2_en1 = mb_convert_encoding($food2[0],'UTF-8','auto');
$food2_en2 = mb_convert_encoding($food2[1],'UTF-8','auto');
$food2_en1 = urlencode($food2_en1);
$food2_en2 = urlencode($food2_en2);



//1個目の商品のAPIのURL作る(キーワードとNGワードを入れる)
$url1 = 'https://app.rakuten.co.jp/services/api/IchibaItem/Search/20140222?format=xml&keyword='.$food1_en1.'%20'.$food1_en2.'&NGKeyword='.$NGkeyword.'&genreId=112115&sort=%2BitemPrice&availability=1&applicationId=*****';

$xml1 = simplexml_load_string(file_get_contents("$url1"));


//2個目の商品のAPIのURL作る(キーワードとNGワードを入れる)
$url1 = 'https://app.rakuten.co.jp/services/api/IchibaItem/Search/20140222?format=xml&keyword='.$food2_en1.'%20'.$food2_en2.'&NGKeyword='.$NGkeyword.'&genreId=112115&sort=%2BitemPrice&availability=1&applicationId=*****';

$xml2 = simplexml_load_string(file_get_contents("$url2"));

//1個目の商品をforeachでまわす
foreach((object) $xml1->Items->Item as $item){

        $name = $item -> itemName;//商品名

        if (strpos($name, $food1[0]) !== FALSE){

        //繰り返し回数による判定
        if ( $i >= 10){
          break;  //10に達したら終了
        } else {
          $i++; //繰り返された回数を1つずつカウント
        $catchcopy = $item -> catchcopy;//キャッチコピー
        $itemurl = $item -> affiliateUrl;//リンクURL
        $imageUrl = $item -> mediumImageUrls -> imageUrl;//画像
        $imageUrl_min = $item -> smallImageUrls -> imageUrl;//小さい画像
        $shopName = $item -> shopName;//ショップネーム
        $itemPrice =$item -> itemPrice;
        $itemPrice = number_format(intval($itemPrice));//金額
        $shopUrl = $item -> shopUrl;//ショップURL

        //比較するために配列に入れなおそうとしましたが、このままだと上書きされるだけ…
        $array_food1 = array($shopName,$catchcopy,$itemurl,$imageUrl,$imageUrl_min,$itemPrice,$itemPrice,shopUrl,$itemPrice);
    }
  }
}

//2個目の商品をforeachでまわす
foreach((object) $xml2->Items->Item as $item){

        $name = $item -> itemName;//商品名

        if (strpos($name, $food2[0]) !== FALSE){

        //繰り返し回数による判定
        if ( $i >= 10){
          break;  //10に達したら終了
        } else {
          $i++; //繰り返された回数を1つずつカウント
        $catchcopy = $item -> catchcopy;//キャッチコピー
        $itemurl = $item -> affiliateUrl;//リンクURL
        $imageUrl = $item -> mediumImageUrls -> imageUrl;//画像
        $imageUrl_min = $item -> smallImageUrls -> imageUrl;//小さい画像
        $shopName = $item -> shopName;//ショップネーム
        $itemPrice =$item -> itemPrice;
        $itemPrice = number_format(intval($itemPrice));//金額
        $shopUrl = $item -> shopUrl;//ショップURL


        //比較するために配列に入れなおそうとしましたが、このままだと上書きされるだけ…
        $array_food2 = array($shopName,$catchcopy,$itemurl,$imageUrl,$imageUrl_min,$itemPrice,$itemPrice,shopUrl,$itemPrice);
    }
  }
}

//配列比較
//var_dump($array_food2);
//var_dump( array_intersect_assoc($array_food1, $array_food2) );


そもそも、配列の中身を比較して、同じショップのものを取り出す、
というのが出来るのかどうかも分からない状態で進めてきています。
でも、この機能は欲しいな〜と思っている次第です!

情報不足、言葉足らずでしたら、追記致しますので、
どうぞよろしくお願いいたします!

補足情報(言語/FW/ツール等のバージョンなど)

PHP:5.4.10

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+2

検索結果をショップ名をキーにした連想配列に格納してはどうでしょうか。
サンプルを作ってみましたので参考にしてみてください。

// 検索結果をショップ名をキーにした連想配列に詰める
$result["shop-a"][] = array("item"=>"猫缶A","price"=>100,"url"=>"http://...");
$result["shop-a"][] = array("item"=>"猫缶B","price"=>150,"url"=>"http://...");
$result["shop-b"][] = array("item"=>"猫缶A","price"=>105,"url"=>"http://...");
$result["shop-c"][] = array("item"=>"猫缶A","price"=>98,"url"=>"http://...");
$result["shop-c"][] = array("item"=>"猫缶B","price"=>110,"url"=>"http://...");

// 結果が2件以上のショップだけを抽出する
$result2 = array_filter($result, function($r){
    return count($r)>=2;
});

// 商品の合計の小さい順に並び替え
uasort($result2,function($r1,$r2){
    return array_sum(array_column($r1,"price")) > array_sum(array_column($r2,"price"));
});

var_dump($result2);


結果

array(2) {
  ["shop-c"]=>
  array(2) {
    [0]=>
    array(3) {
      ["item"]=>
      string(7) "猫缶A"
      ["price"]=>
      int(98)
      ["url"]=>
      string(10) "http://..."
    }
    [1]=>
    array(3) {
      ["item"]=>
      string(7) "猫缶B"
      ["price"]=>
      int(110)
      ["url"]=>
      string(10) "http://..."
    }
  }
  ["shop-a"]=>
  array(2) {
    [0]=>
    array(3) {
      ["item"]=>
      string(7) "猫缶A"
      ["price"]=>
      int(100)
      ["url"]=>
      string(10) "http://..."
    }
    [1]=>
    array(3) {
      ["item"]=>
      string(7) "猫缶B"
      ["price"]=>
      int(150)
      ["url"]=>
      string(10) "http://..."
    }
  }
}

追記

$food1 = "猫缶";        //$_POST['food1']; //1つ目のselectのoptionのvalue
$food2 = "カリカリ";    //$_POST['food2']; //2つ目のselectのoptionのvalue

// 検索結果をショップ名をキーにした連想配列に詰める
$result["shop-a"][$food1][] = array("item"=>"猫缶A","price"=>100,"url"=>"http://...");
$result["shop-a"][$food1][] = array("item"=>"猫缶A(関東限定)","price"=>100,"url"=>"http://...");
$result["shop-a"][$food2][] = array("item"=>"猫缶B","price"=>150,"url"=>"http://...");
$result["shop-b"][$food1][] = array("item"=>"猫缶A","price"=>105,"url"=>"http://...");
$result["shop-c"][$food1][] = array("item"=>"猫缶A","price"=>98,"url"=>"http://...");
$result["shop-c"][$food2][] = array("item"=>"猫缶B","price"=>110,"url"=>"http://...");

// food1とfood2の両方の結果があるショップだけを抽出する
$result2 = array_filter($result, function($r){
    return count($r)>=2;
});

// 並び替えの処理は、複数商品があった場合どうするかによるので今回は省略

var_dump($result2);


結果

array(2) {
  ["shop-a"]=>
  array(2) {
    ["猫缶"]=>
    array(2) {
      [0]=>
      array(3) {
        ["item"]=>
        string(7) "猫缶A"
        ["price"]=>
        int(100)
        ["url"]=>
        string(10) "http://..."
      }
      [1]=>
      array(3) {
        ["item"]=>
        string(21) "猫缶A(関東限定)"
        ["price"]=>
        int(100)
        ["url"]=>
        string(10) "http://..."
      }
    }
    ["カリカリ"]=>
    array(1) {
      [0]=>
      array(3) {
        ["item"]=>
        string(7) "猫缶B"
        ["price"]=>
        int(150)
        ["url"]=>
        string(10) "http://..."
      }
    }
  }
  ["shop-c"]=>
  array(2) {
    ["猫缶"]=>
    array(1) {
      [0]=>
      array(3) {
        ["item"]=>
        string(7) "猫缶A"
        ["price"]=>
        int(98)
        ["url"]=>
        string(10) "http://..."
      }
    }
    ["カリカリ"]=>
    array(1) {
      [0]=>
      array(3) {
        ["item"]=>
        string(7) "猫缶B"
        ["price"]=>
        int(110)
        ["url"]=>
        string(10) "http://..."
      }
    }
  }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/24 19:42

    ttyp03さん
    丁寧にサンプルソースまで作っていただきありがとうございます!
    「ショップ名をキーにして連想配列」というのが出来ることをここで知りました!

    なんとか「結果が2件以上のショップだけを抽出する」まで出来たのですが、
    楽天APIの問題(?)で、
    同じショップ名で同じ商品を出していることもあるようなのです。
    (例:「猫缶A」と「猫缶A(関東限定価格)」など)

    そこで、selectタグごとの「food1」「food2」を一緒くたにしないで、
    「food1」のショップ名が、「food2」にあるか見ていく、ということは出来ますか?

    どうぞよろしくお願い致します。

    キャンセル

  • 2016/08/25 08:55

    どういう風に処理させたいのかイメージがつかめませんが、結果を保持する配列を次のような形にしてはどうでしょうか。

    result[ショップ名]
     food[food1名]
      [0]結果
      [1]結果
      …
     food[food2名]
      [0]結果
      [1]結果
      …

    こうすれば、ショップごとにfood1と2の結果を別々に管理できます。
    サンプルを追記しておきますので参考にしてみてください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • トップ
  • PHPに関する質問
  • PHPと楽天APIを使って、2つの商品の最安値ランキングから、ショップが重複するものをさらにランキングに