この記事では、【特定のカテゴリに該当】かつ【特定のタグをもつ】商品のみ取得し、一覧表示する方法を紹介します。(以下2記事の応用編です)
デバッグモードを設定しておくと、エラーが起きたときに詳細情報が表示されるようになります。
エラー箇所を探しやすくなるので、開発前に設定しておくのをオススメします。
デバッグモードの設定方法については 以下記事 で解説しています。
カスタマイズ後は、デバッグモードの解除を忘れないように。
カテゴリー商品一覧ページの作成手順
- 本機能を実装するための新規ページを作成。
- ①で作成した、新規ページのControllerファイルを修正。
- ①で作成した、新規ページのTwigファイルを修正。
- EC-CUBE管理画面にてキャッシュを削除。
Controllerの作成
STEP 1で作成したControllerファイルを以下の通り修正します。
<?php
namespace Customize\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Eccube\Controller\AbstractController;
use Eccube\Repository\ProductRepository; // ProductRepositoryの使用を宣言
class SampleController extends AbstractController
{
/**
* ProductRepositoryのインスタンスを保持するプロパティ
* @var ProductRepository
*/
protected $productRepository;
/**
* コンストラクタでProductRepositoryのインスタンスを注入
* @param ProductRepository $productRepository
*/
public function __construct(ProductRepository $productRepository) {
$this->productRepository = $productRepository;
}
/**
* @Route("/sample", name="sample")
* @Template("sample.twig")
*/
public function index(Request $request)
{
// 例: カテゴリID=1 かつ タグID=4 の「公開商品」を取得
$customQb = $this->productRepository->createQueryBuilder('p')
->select('DISTINCT p') // 多対多のJOINで重複するのを防ぐ
// カテゴリ条件
->innerJoin('p.ProductCategories', 'pc')
->innerJoin('pc.Category', 'c')
->andWhere('c.id = :Category')
// タグ条件
->innerJoin('p.ProductTag', 'pt')
->innerJoin('pt.Tag', 't')
->andWhere('t.id = :Tag')
// 公開商品のみに絞る(任意)
->andWhere('p.Status = :status')
// 並び順(任意)
->addOrderBy('p.update_date', 'DESC')
// パラメータ
->setParameter('Category', 1)
->setParameter('Tag', 4)
// 定数を使う場合: ->setParameter('status', ProductStatus::DISPLAY_SHOW)
->setParameter('status', 1);
$products = $customQb->getQuery()->getResult();
return [
// Twigテンプレートに渡す変数「Products」に、$products のデータを設定
'Products' => $products,
];
}
}
このControllerによって、@Routeで指定したURLにアクセスしたときに、データベースから特定のカテゴリーとタグに該当する商品データを引っ張ってくることができます。
上記コードでは、URL「ドメイン名/sample」にアクセスしたときに、ID=1のカテゴリーに属し、かつID=4のタグを持つ商品データが取得されます。カテゴリーIDおよびタグIDは、管理画面の商品管理 > カテゴリ管理またはタグ管理 で確認できます。ご自身の状況に合わせて、適宜修正してください。
なお、RepositoryやControllerの仕組みや使い方については、以下記事にて解説しています。
再利用性やメンテナンス性の観点から、このようなデータベースに関するクエリはリポジトリで定義することが推奨されています。
クエリの移行方法は以下記事で紹介しているので、合わせて設定しておくのをお薦めします。
新規ページ(Twigテンプレート)の編集
管理画面のコンテンツ管理 > ページ管理から、Twigテンプレートを編集します。
なお、このテンプレートの大部分は、デフォルトで用意されている「商品一覧ページ」を参考にしています。
{% extends 'default_frame.twig' %}
{% block main %}
<div class="ec-shelfRole">
<ul class="ec-shelfGrid">
{# Productsに格納されているデータを順に取り出し、Productに代入 #}
{% for Product in Products %}
<li class="ec-shelfGrid__item">
<a href="{{ url('product_detail', {'id': Product.id}) }}">
{# 商品画像の表示 #}
<p class="ec-shelfGrid__item-image">
<img src="{{ asset(Product.main_list_image|no_image_product, 'save_image') }}" alt="{{ Product.name }}" loading="lazy">
</p>
{# 商品名の表示 #}
<p>{{ Product.name }}</p>
{# 価格の表示 #}
<p class="price02-default">
{% if Product.hasProductClass %}
{% if Product.getPrice02Min == Product.getPrice02Max %}
{{ Product.getPrice02IncTaxMin|price }}
{% else %}
{{ Product.getPrice02IncTaxMin|price }} ~ {{ Product.getPrice02IncTaxMax|price }}
{% endif %}
{% else %}
{{ Product.getPrice02IncTaxMin|price }}
{% endif %}
</p>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
STEP 1で作成したControllerにより、Productsには$producs(ID=1のカテゴリーに該当し、かつID=4のタグを持つ商品情報)が格納されています。その商品情報を、for文を用いて「Product」として一つずつ取り出し、
- Product.main_list_image
-
商品のメイン画像
- Product.name
-
商品名
- Product.getPrice
-
商品の価格
というように表示しています。
商品データの他の値(商品IDなど)を表示させることも可能です。
なお、Twigテンプレートのfor文については、以下記事で解説しています。
キャッシュを削除
ここまでで準備完了です。
管理画面からキャッシュを削除して、ページにアクセスしてみましょう。

問題がなければ、指定したIDのカテゴリーとタグに該当する商品一覧が表示されているはずです。!
まとめ
以上、特定のカテゴリーとタグに属する商品のみを表示するページを作る方法を紹介しました。特集記事などの作成の際に、ぜひ利用してみてください。
