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

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

ただいまの
回答率

88.64%

【Smarty】foreachにて配列の中身を出力する際、内容が同じ要素は出力しないようにしたい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 3,519

katsuo_isono

score 63

【やりたいこと】
Smartyのtpl内でforeachを使って配列の中身を出力する際、内容が全く同じ要素がある場合、その要素は出力しないようにしたい

【現状】
同じ要素が複数出力されてしまっている

【背景】
EC-CUBE2.13を使用してサイトを作成しています。
list.tplで「ある特定のカテゴリーの商品において、その商品すべてのメーカーの一覧を表示させる」という処理を記述しています。
コードは下記の通りです。

            <!--▼メーカー一覧-->
             <!--{if $arrSearchData.category_id == 1}--><!-- 特定のカテゴリーページのみ表示 -->
                    <ul class="makerlist_area">
                    <!--{foreach from=$arrAllProducts item=maker name=foo}-->
                            <li class="maker_name"><a href="<!--{$smarty.const.ROOT_URLPATH}-->products/list.php?category_id=1&maker_id=<!--{$maker.maker_id|h}-->"><!--{$maker.maker_name|h}--></a></li>
                    <!--{/foreach}-->
                    </ul>
             <!--{/if}-->
            <!-- ▲メーカー一覧-->

代替案として、JSを用いて「makerlist_areaクラスの中で、全く同じ要素が存在する場合1つだけ表示させる処理を加える」というアイデアも思いついたのですが、
どうせなら綺麗にforeachの中で処理したいと思い、何かいい方法がないか、投稿させて頂きました。

よろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+1

選抜メーカーリスト用のブロックを追加して
templateに渡す前に配列をフィルタリングしたほうがいいと思います。

--------------以下 追記--------------
私ならこうするかな?..的なところを大まかに追記しておきます

Smartyにはtemplate上でarray_uniqueを実行する関数は用意されていませんので
あらかじめ 必要なデータを絞り込んで 配列を作り直す必要があると思います、

まず、EC-CUBEの管理画面→デザイン設定→ブロック設定から ブロックを新規に作成
(ここでは仮にブロック名:メーカーリスト ファイル名:maker_list.tplとします)

データベースのdtb_blocテーブルに追加されたメーカーリストのレコード上でphp_pathフィールドにphpのパスを指定します。
(何処のディレクトリでも構いませんがここでは解かり易く仮に frontparts/bloc/maker_list.phpとします)

EC-CUBE内のディレクトリhtmlfrontpartsblocフォルダーにデータベースのdtb_blocで指定したmaker_list.phpを設置します。

一先ずここまでの操作で 管理画面→デザイン設定→レイアウト設定で必要なページにメーカーリストブロックを配置すればmaker_list.phpの内容がサイト内に表示されるようになります。

maker_list.phpの内容ですが..今回は登録済みのデータを抜粋して表示するだけですので、面倒なEC-CUBE独自の手順を踏んでテンプレートを介さなくても
PHPで直接データを出力してセキュリティー上、何の問題もないと思います。

<?php

if(isset($_GET['category_id'])){
・・・・・・・・・//`$_GET['category_id']`にエスケープ処理くらいは必要
}else{
・・・・・・・・・
}

require_once realpath(dirname(__FILE__)) . '/../../../data/config/config.php';
//(data/frontparts/bloc/からのパスを想定 EC-CUBEで登録したDB情報の定数を取得)
    try {
        $pdo = new PDO(DB_TYPE.':host='.DB_SERVER.';dbname='.DB_NAME.';charset=utf8',DB_USER,DB_PASSWORD,array(PDO::ATTR_EMULATE_PREPARES => false));
        //これで繋がるはずです。
        $pdo->query('SET NAMES utf8');
        $stmt = $pdo->query("********");

        ・・・・・・・・・
        ・・・・・・・・・
        ・・・・・・・・・
    } catch (PDOException $e) {
        exit($e->getMessage());
    }

//あとは`foreach`なりなんなりで`echo `なり`print`なり

//こんな感じで必要な処理を記述してください。

ちなみに.dtb_productsテーブルとdtb_makerテーブルは 双方のmaker_idフィールドで直接紐付されていますがdtb_categorydtb_products_classで繋がってます。
DBの構造はdocsフォルダ内にtable_definition.xlsで保存されてますから確認してください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/02 18:38

    ご返信遅くなり申し訳ありません!
    ご回答ありがとうございます。

    こちらの内容で、指定したカテゴリIDのページを開いている場合に、selectで重複なしのメーカー一覧を表示するという実装を試してみます。
    まだ$pdo->queryの処理が上手くいってませんが…

    キャンセル

  • 2016/05/02 21:32 編集

    検証した訳ではないので 何処か間違ってたらごめんなさい><;

    $_GET['category_id']のパラメータを$category_idに代入したとして

    $stmt = $pdo->query("
    SELECT `dtb_maker`.`maker_id` AS `markerid`, `dtb_maker`.`name` AS `markername` FROM `dtb_maker` LEFT JOIN `dtb_products` ON (`dtb_maker`.`maker_id` = `dtb_products`.`maker_id`) LEFT JOIN `dtb_products_class` ON(`dtb_products`.`product_id` = `dtb_products_class`.`product_id`) WHERE `dtb_products_class`.`classcategory_id1` = '$category_id' OR `dtb_products_class`.`classcategory_id2` = '$category_id'
    ");

    while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $markerdata[] = $data;
    }

    $marker = array_unique($markerdata);

    foreach($marker as $val){
    echo $val['markerid'].'=>'.$val['markername'];
    }

    こんな感じで行けませんかね?

    キャンセル

  • 2016/05/06 14:22

    ご回答ありがとうございます。
    $category_idは固定(表示させたいのは特定のカテゴリーリスト1ページのみ)ですので、
    pdoの構文を下記のように致しました。

    $stmt = $pdo->query("SELECT `dtb_maker`.`maker_id` AS `markerid`, `dtb_maker`.`name` AS `markername` FROM `dtb_maker` LEFT JOIN `dtb_products` ON (`dtb_maker`.`maker_id` = `dtb_products`.`maker_id`) LEFT JOIN `dtb_product_categories` ON(`dtb_products`.`product_id` = `dtb_product_categories`.`product_id`) WHERE `dtb_product_categories`.`category_id` = ●●");

    また、$makerdataは多次元配列のため、第二引数にSORT_REGULARを入れることで正常に重複削除ができ、画面上にも表示されました!

    とても詳しいご回答ありがとうございます!!

    キャンセル

  • 2016/05/06 17:29

    無事に解決して良かったです..♪
    わざわざコメント ありがとうございます^^

    キャンセル

+1

新しく配列を宣言して、その配列に$maker.maker_idが存在しなければければ表示処理とその配列に$maker.maker_idを入れる、というのはどうでしょうか。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/02 18:39

    ご返信遅くなり申し訳ありません!
    ご回答ありがとうございます。

    大まかな流れの参考にさせて頂きました。ありがとうございます。

    キャンセル

+1

『foreachの中で処理をする』、よりも『foreachで回す前に処理をする』ほうがいいのではないかな?と思います。
array_uniqueを使えば簡単ですし。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/02 18:42

    ご返信遅くなり申し訳ありません!
    ご回答ありがとうございます。

    表示するページ内の全商品IDとメーカーIDを取得し、メーカーIDを取得する際に
    メーカーIDが同じ場合は表示させない、という処理で対応しようと思います。

    キャンセル

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

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

関連した質問

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

  • トップ
  • PHPに関する質問
  • 【Smarty】foreachにて配列の中身を出力する際、内容が同じ要素は出力しないようにしたい