EC-CUBEでは、商品のカテゴリ一覧は用意されていますがタグ一覧はありません。
カテゴリ一覧は「?category_id=1」というパラメータによって、商品の絞り込みが行われています。同じように、タグIDでも絞り込みができるようにカスタマイズする方法をご紹介したいと思います。
EC-CUBE4でタグIDによる商品一覧の絞り込みを実装する方法
今回実装した環境
タグIDによる商品の絞り込みを実装した環境は、以下の通りです。EC-CUBEのバージョンが異なると動かない可能性もありますので、開発環境で十分に検証したうえで実装してください。
- EC-CUBEバージョン:EC-CUBE4.0.6-p1
- サーバー:エックスサーバー
- PHP:PHP7.3.33
- データベース:MySQL 5.7.27
ファイルの追加
まずは、以下2つのファイルを追加していきます。フォルダが存在しない場合は作成してください。
- /app/Customize/Form/Extension/SearchProductTypeExtension.php
- /app/Customize/Repository/TagIdSearchCustomizer.php
SearchProductTypeExtension.phpの中身は以下のようにします。コピペでOKです。
<?php
namespace Customize\Form\Extension;
use Eccube\Form\Type\SearchProductType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
class SearchProductTypeExtension extends AbstractTypeExtension {
  /**
   * {@inheritdoc}
   */
  public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('tag_id', HiddenType::class, []);
  }
  /**
   * {@inheritdoc}
   */
  public function getExtendedType() {
    return SearchProductType::class;
  }
}TagIdSearchCustomizer.phpの中身は以下のようにします。こちらもコピペでOKです。
<?php
namespace Customize\Repository;
use Eccube\Doctrine\Query\QueryCustomizer;
use Eccube\Repository\QueryKey;
use Doctrine\ORM\QueryBuilder;
class TagIdSearchCustomizer implements QueryCustomizer {
  public function customize(QueryBuilder $builder, $params, $queryKey) {
    if (!empty($params['tag_id']) && $params['tag_id']) {
      $builder->innerJoin('p.ProductTag', 'pt');
      $builder->andWhere('pt.Tag = :tag_id');
      $builder->setParameter('tag_id', $params['tag_id']);
    }
  }
  public function getQueryKey(): string {
    return QueryKey::PRODUCT_SEARCH;
  }
}
上記2つのファイルを追加したら、EC-CUBEの管理画面で[コンテンツ管理] – [キャッシュ管理]にアクセスしキャッシュをクリアします。
以下のように「tag_id」を指定したURLにアクセスすると、指定したタグIDに属する商品の一覧が表示されます。
https://example.com/products/list?tag_id=1パンくずリストの調整
タグ一覧は出力できるようになりましたが、タグ一覧ではパンくずリストが「全て」しか表示されないのでパンくずも調整します。(デフォルトテンプレートの場合)

「/app/template/default/Product/list.twig」内に、以下を追加してあげます。
{% set Tags = repository('Eccube\\Entity\\Tag').getList() %}
{% set now_tag_id = app.request.query.get('tag_id') %}
{% if now_tag_id is not null %}
  {% for Tag in Tags %}
    {% if now_tag_id == Tag.id %}
      <li class="ec-topicpath__divider">/</li>
      <li class="ec-topicpath__item"><a href="{{ url('product_list') }}?tag_id={{ Tag.id }}">{{ Tag.name }}</a></li>
    {% endif %}
  {% endfor %}
{% endif %}list.twig内の「.ec-topicpath」がパンくずリストなので、そこに追加します。全体像としては、以下のようになります。
<div class="ec-searchnavRole__topicpath">
  <ol class="ec-topicpath">
    <li class="ec-topicpath__item"><a href="{{ url('product_list') }}">{{ '全て'|trans }}</a>
    </li>
    {% set Tags = repository('Eccube\\Entity\\Tag').getList() %}
    {% set now_tag_id = app.request.query.get('tag_id') %}
    {% if now_tag_id is not null %}
      {% for Tag in Tags %}
        {% if now_tag_id == Tag.id %}
          <li class="ec-topicpath__divider">/</li>
          <li class="ec-topicpath__item"><a href="{{ url('product_list') }}?tag_id={{ Tag.id }}">{{ Tag.name }}</a></li>
        {% endif %}
      {% endfor %}
    {% endif %}
    {% if Category is not null %}
      {% for Path in Category.path %}
        <li class="ec-topicpath__divider">|</li>
        <li class="ec-topicpath__item{% if loop.last %}--active{% endif %}"><a href="{{ url('product_list') }}?category_id={{ Path.id }}">{{ Path.name }}</a>
        </li>
      {% endfor %}
    {% endif %}
    {% if search_form.vars.value and search_form.vars.value.name %}
      <li class="ec-topicpath__divider">|</li>
      <li class="ec-topicpath__item">{{ '「%name%」の検索結果'|trans({ '%name%': search_form.vars.value.name }) }}</li>
    {% endif %}
  </ol>
</div>商品詳細ページでリンク付きのタグを表示
商品詳細ページでタグ一覧へのリンク付きのタグを表示したい場合は、「/app/template/default/Product/detail.twig」を変更します。
タグを表示させたい箇所に以下を記述することで、一覧へのリンク付きタグを出力できます。
{% if Product.Tags is not empty %}
<ul class="ec-productRole__tags">
  {% for Tag in Product.Tags %}
    <li class="ec-productRole__tag tag_{{ Tag.id }}">
      <a href="{{ url('product_list') }}?tag_id={{ Tag.id }}">{{ Tag }}</a>
    </li>
  {% endfor %}
</ul>
{% endif %}あとがき
EC-CUBE4系でタグ一覧ページを実装したい時は、上述した方法をお試しください。
なお、「タグID検索 for EC-CUBE4」という有料プラグインでも同じことができますので、プラグインの購入も視野に入れて検討するのが良いかと思います。


大変興味深い記事をありがとうございます。
当方EC-CUBE4.1.0ですが、本記事のSearchProductTypeExtension.phpを組み込むとエラー画面となり、動作いたしませんでした。残念です。
コメントありがとうございます。
4.0系と4.1系ではSymfonyのバージョンが違うので、書き方も若干異なるんですよね。(上位互換のないところがEC-CUBEのやっかいな部分ですよね…)
全く別のカスタマイズですが、こちらの記事で4.1と4.0の書き方の違いも紹介しております。
未検証なので何とも言えませんが、SearchProductTypeExtension.phpの「public function getExtendedType()」の部分を書き換えると良いかもしれません。