EC-CUBE4では商品一覧への絞り込み条件追加をカスタマイズすることができます。今回はもっともご要望が多い「タグでの検索」カスタマイズ方法をご紹介します。
やや難易度は高いですが、タグの場合は複数のタグで同時に検索したいというご要望が多いので、タグを複数指定する方法をご紹介します。
複数ではなく1つで良いという場合は、コード内で‘multiple’ => true,を’multiple’ => false,に変えてください。
EC-CUBEにはタグという機能がありますが、商品ページにラベルを表示するだけで、絞り込み機能はデフォルトでありません。これから実装手順をご紹介いたします。
1. AbstractTypeExtensionでSearchProductTypeを拡張
app/Customize/Form/Extension/SearchProductTypeTagExtension.php という新規ファイルを設置します。
<?php namespace Customize\Form\Extension; use Eccube\Entity\Tag; use Eccube\Form\Type\SearchProductType; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; /** * タグの検索フォームを追加 * @see https://umebius.com/eccube/product_list_tag_search/ */ class SearchProductTypeTagExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add( 'tag', EntityType::class, [ 'class' => Tag::class, 'required' => false, 'choice_label' => 'name', 'expanded' => true, 'multiple' => true, 'placeholder' => false, 'constraints' => [ ], ] ) ; } /** * {@inheritdoc} */ public function getExtendedType() { return SearchProductType::class; } /** * Return the class of the type being extended. */ public static function getExtendedTypes(): iterable { return [SearchProductType::class]; } }
2. QueryCustomizerで検索ロジックの追加
app/Customize/QueryCustomize/FrontProductTagCustomizer.php を新規追加
QueryCustomizerにより商品一覧の検索ロジックをカスタマイズします。
<?php /* * This file is part of EC-CUBE * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * * http://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Customize\QueryCustomize; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\QueryBuilder; use Eccube\Doctrine\Query\QueryCustomizer; use Eccube\Entity\Tag; use Eccube\Repository\QueryKey; /** * タグの検索ロジックを追加 * * @see https://umebius.com/eccube/product_list_tag_search/ */ class FrontProductTagCustomizer implements QueryCustomizer { /** * @param QueryBuilder $builder * @param array $params * @param string $queryKey */ final public function customize(QueryBuilder $builder, $params, $queryKey) { if (isset($params['tag'])) { if ($params['tag'] instanceof ArrayCollection) { if (count($params['tag'])) { $ids = $params['tag']->map(function ($var) {return $var->getId();})->toArray(); $builder->leftJoin('p.ProductTag', 'product_tag'); $builder->leftJoin('product_tag.Tag', 'tag'); $builder->andWhere($builder->expr()->in('tag.id', $ids)); } } else if ($params['tag'] instanceof Tag){ $builder->leftJoin('p.ProductTag', 'product_tag'); $builder->leftJoin('product_tag.Tag', 'tag'); $builder->andWhere($builder->expr()->eq('tag.id', $params['tag']->getId())); } } } /** * カスタマイズ対象のキーを返します。 * * @return string */ public function getQueryKey() { return QueryKey::PRODUCT_SEARCH; } }
ここまでのカスタマイズで、tag[]パラメータをつけると、タグで絞り込んだ商品一覧が表示されるのではないでしょうか。動作確認してみてください。
http://example.com/shop/list?tag[]=(タグID)
しかし現状では並び替えを行うと絞り込みが解除されてしまいます。
3. 並び替えやページネーションに対応(複数検索の場合のみ対応が必要)
複数検索を実装するときに並び替えやページネーションに対応させるポイントです。
テンプレートのProduct/list.twigを修正します。
{% for item in search_form %} <input type="hidden" id="{{ item.vars.id }}" name="{{ item.vars.full_name }}" {% if item.vars.value is not empty %}value="{{ item.vars.value }}" {% endif %}/> {% endfor %}
となっている部分を、下記のように変更してください。
{% for item in search_form %} {# タグの複数検索に対応 @see https://umebius.com/eccube/product_list_tag_search/ #} {% if item.vars.value is iterable %} {% for val in item.vars.value %} <input type="hidden" id="{{ item.vars.id }}" name="{{ item.vars.full_name }}[]" value="{{ val }}"/> {% endfor %} {% else %} <input type="hidden" id="{{ item.vars.id }}" name="{{ item.vars.full_name }}" {% if item.vars.value is not empty %}value="{{ item.vars.value }}" {% endif %}/> {% endif %} {% endfor %}
4. 検索フォームを表示
app/Customize/Form/Extension/SearchProductBlockTypeExtension.php という新規ファイルを設置します。
EC-CUBEバージョン4.1以上では上で作成したSearchProductTypeExtension.phpにまとめることができるのですが、4.0が対応していないはずなので、ここでは2ファイルに分けています。
<?php namespace Customize\Form\Extension; use Doctrine\ORM\EntityManagerInterface; use Eccube\Entity\Tag; use Eccube\Form\Type\SearchProductBlockType; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; class SearchProductBlockTypeExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add( 'tag', EntityType::class, [ 'class' => Tag::class, 'required' => false, 'choice_label' => 'name', 'expanded' => true, 'multiple' => true, 'placeholder' => false, 'constraints' => [ ], ] ) ; } /** * {@inheritdoc} */ public function getExtendedType() { return SearchProductBlockType::class; } /** * Return the class of the type being extended. */ public static function getExtendedTypes(): iterable { return [SearchProductBlockType::class]; } }
あとは、テンプレートのBlock/search_product.twigにフォームの表示を追加すれば検索ができるようになります。
{{ form_widget(form.tag) }}
EC-CUBEに関するお問い合わせ
[重要]現在公式にセキュリティサポートが切れていないPHPは8.1以上、MySQLは8.0以上で、対応しているEC-CUBEバージョンは4.2以上です。古いEC-CUBEを使っている方は適切なタイミングでバージョンアップをご検討ください。