読み込みが終了しない場合は、しばらく待つか、リロードを行なってください。
If loading does not finish, wait for a while or reload.
エンジニア向けの情報を発信するブログです。
どなたでも発信できます。
お好きに利用していただれば幸いです。
📁 app/Customize/Repository/Extension/ProductRepositoryExtension.php <?php namespace Customize\Repository\Extension; use Eccube\Repository\ProductRepository; class ProductRepositoryExtension extends ProductRepository { // }
📁 app/config/eccube/services.yaml ~~ 省略 Eccube\Form\Extension\HTMLPurifierTextTypeExtension: arguments: - '@Eccube\Request\Context' tags: - { name: form.type_extension, priority: -99, extended_type: Symfony\Component\Form\Extension\Core\Type\TextType } // ↓以下を追加 Customize\Repository\Extension\ProductRepositoryExtension: autowire: true decorates: Eccube\Repository\ProductRepository
📁 app/Customize/Repository/Extension/ProductRepositoryExtension.php <?php namespace Customize\Repository\Extension; use Eccube\Repository\ProductRepository; // ↓関数に必要なクラスをuseする use Eccube\Repository\QueryKey; use Eccube\Util\StringUtil; class ProductRepositoryExtension extends ProductRepository { // ↓コピペ /** * get query builder. * * @param array $searchData * * @return \Doctrine\ORM\QueryBuilder */ public function getQueryBuilderBySearchData($searchData) { $qb = $this->createQueryBuilder('p') ->andWhere('p.Status = 1'); // category $categoryJoin = false; if (!empty($searchData['category_id']) && $searchData['category_id']) { $Categories = $searchData['category_id']->getSelfAndDescendants(); if ($Categories) { $qb ->innerJoin('p.ProductCategories', 'pct') ->innerJoin('pct.Category', 'c') ->andWhere($qb->expr()->in('pct.Category', ':Categories')) ->setParameter('Categories', $Categories); $categoryJoin = true; } } // name if (isset($searchData['name']) && StringUtil::isNotBlank($searchData['name'])) { $keywords = preg_split('/[\s ]+/u', str_replace(['%', '_'], ['\\%', '\\_'], $searchData['name']), -1, PREG_SPLIT_NO_EMPTY); foreach ($keywords as $index => $keyword) { $key = sprintf('keyword%s', $index); $qb ->andWhere(sprintf('NORMALIZE(p.name) LIKE NORMALIZE(:%s) OR NORMALIZE(p.search_word) LIKE NORMALIZE(:%s) OR EXISTS (SELECT wpc%d FROM \Eccube\Entity\ProductClass wpc%d WHERE p = wpc%d.Product AND NORMALIZE(wpc%d.code) LIKE NORMALIZE(:%s))', $key, $key, $index, $index, $index, $index, $key)) ->setParameter($key, '%'.$keyword.'%'); } } // Order By // 価格低い順 $config = $this->eccubeConfig; if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_lower']) { //@see http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html $qb->addSelect('MIN(pc.price02) as HIDDEN price02_min'); $qb->innerJoin('p.ProductClasses', 'pc'); $qb->andWhere('pc.visible = true'); $qb->groupBy('p.id'); $qb->orderBy('price02_min', 'ASC'); $qb->addOrderBy('p.id', 'DESC'); // 価格高い順 } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) { $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max'); $qb->innerJoin('p.ProductClasses', 'pc'); $qb->andWhere('pc.visible = true'); $qb->groupBy('p.id'); $qb->orderBy('price02_max', 'DESC'); $qb->addOrderBy('p.id', 'DESC'); // 新着順 } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_newer']) { // 在庫切れ商品非表示の設定が有効時対応 // @see https://github.com/EC-CUBE/ec-cube/issues/1998 if ($this->getEntityManager()->getFilters()->isEnabled('option_nostock_hidden') == true) { $qb->innerJoin('p.ProductClasses', 'pc'); $qb->andWhere('pc.visible = true'); } $qb->orderBy('p.create_date', 'DESC'); $qb->addOrderBy('p.id', 'DESC'); } else { if ($categoryJoin === false) { $qb ->leftJoin('p.ProductCategories', 'pct') ->leftJoin('pct.Category', 'c'); } $qb ->addOrderBy('p.id', 'DESC'); } return $this->queries->customize(QueryKey::PRODUCT_SEARCH, $qb, $searchData); } }
// Order By // 価格低い順 $config = $this->eccubeConfig; if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_lower']) { //@see http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html $qb->addSelect('MIN(pc.price02) as HIDDEN price02_min'); $qb->innerJoin('p.ProductClasses', 'pc'); $qb->andWhere('pc.visible = true'); $qb->groupBy('p.id'); $qb->orderBy('price02_min', 'DESC');// 👈 書き換え $qb->addOrderBy('p.id', 'DESC'); // 価格高い順 } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) { $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max'); $qb->innerJoin('p.ProductClasses', 'pc'); $qb->andWhere('pc.visible = true'); $qb->groupBy('p.id'); $qb->orderBy('price02_max', 'ASC');// 👈 書き換え $qb->addOrderBy('p.id', 'DESC'); // 新着順 } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_newer']) { // 在庫切れ商品非表示の設定が有効時対応 // @see https://github.com/EC-CUBE/ec-cube/issues/1998 if ($this->getEntityManager()->getFilters()->isEnabled('option_nostock_hidden') == true) { $qb->innerJoin('p.ProductClasses', 'pc'); $qb->andWhere('pc.visible = true'); } $qb->orderBy('p.create_date', 'DESC'); $qb->addOrderBy('p.id', 'DESC'); } else { if ($categoryJoin === false) { $qb ->leftJoin('p.ProductCategories', 'pct') ->leftJoin('pct.Category', 'c'); } $qb ->addOrderBy('p.id', 'DESC'); }
📁 app/Customize/Controller/ProductController.php <?php namespace Customize\Controller; use Eccube\Event\EccubeEvents; use Eccube\Event\EventArgs; use Eccube\Form\Type\AddCartType; use Eccube\Form\Type\Master\ProductListMaxType; use Eccube\Form\Type\Master\ProductListOrderByType; use Eccube\Form\Type\SearchProductType; use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination; use Knp\Component\Pager\PaginatorInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class ProductController extends \Eccube\Controller\ProductController { /** * 商品一覧画面. * * @Route("/products/list", name="product_list", methods={"GET"}) * @Template("Product/list.twig") */ public function index(Request $request, PaginatorInterface $paginator) { // Doctrine SQLFilter if ($this->BaseInfo->isOptionNostockHidden()) { $this->entityManager->getFilters()->enable('option_nostock_hidden'); } // handleRequestは空のqueryの場合は無視するため if ($request->getMethod() === 'GET') { $request->query->set('pageno', $request->query->get('pageno', '')); } // searchForm /* @var $builder \Symfony\Component\Form\FormBuilderInterface */ $builder = $this->formFactory->createNamedBuilder('', SearchProductType::class); if ($request->getMethod() === 'GET') { $builder->setMethod('GET'); } $event = new EventArgs( [ 'builder' => $builder, ], $request ); $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_INITIALIZE, $event); /* @var $searchForm \Symfony\Component\Form\FormInterface */ $searchForm = $builder->getForm(); $searchForm->handleRequest($request); // paginator $searchData = $searchForm->getData(); // 👇以下の関数名を変更 $qb = $this->productRepository->customizeGetQueryBuilderBySearchData($searchData); $event = new EventArgs( [ 'searchData' => $searchData, 'qb' => $qb, ], $request ); $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_SEARCH, $event); $searchData = $event->getArgument('searchData'); $query = $qb->getQuery() ->useResultCache(true, $this->eccubeConfig['eccube_result_cache_lifetime_short']); /** @var SlidingPagination $pagination */ $pagination = $paginator->paginate( $query, !empty($searchData['pageno']) ? $searchData['pageno'] : 1, !empty($searchData['disp_number']) ? $searchData['disp_number']->getId() : $this->productListMaxRepository->findOneBy([], ['sort_no' => 'ASC'])->getId() ); $ids = []; foreach ($pagination as $Product) { $ids[] = $Product->getId(); } $ProductsAndClassCategories = $this->productRepository->findProductsWithSortedClassCategories($ids, 'p.id'); // addCart form $forms = []; foreach ($pagination as $Product) { /* @var $builder \Symfony\Component\Form\FormBuilderInterface */ $builder = $this->formFactory->createNamedBuilder( '', AddCartType::class, null, [ 'product' => $ProductsAndClassCategories[$Product->getId()], 'allow_extra_fields' => true, ] ); $addCartForm = $builder->getForm(); $forms[$Product->getId()] = $addCartForm->createView(); } // 表示件数 $builder = $this->formFactory->createNamedBuilder( 'disp_number', ProductListMaxType::class, null, [ 'required' => false, 'allow_extra_fields' => true, ] ); if ($request->getMethod() === 'GET') { $builder->setMethod('GET'); } $event = new EventArgs( [ 'builder' => $builder, ], $request ); $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_DISP, $event); $dispNumberForm = $builder->getForm(); $dispNumberForm->handleRequest($request); // ソート順 $builder = $this->formFactory->createNamedBuilder( 'orderby', ProductListOrderByType::class, null, [ 'required' => false, 'allow_extra_fields' => true, ] ); if ($request->getMethod() === 'GET') { $builder->setMethod('GET'); } $event = new EventArgs( [ 'builder' => $builder, ], $request ); $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_ORDER, $event); $orderByForm = $builder->getForm(); $orderByForm->handleRequest($request); $Category = $searchForm->get('category_id')->getData(); return [ 'subtitle' => $this->getPageTitle($searchData), 'pagination' => $pagination, 'search_form' => $searchForm->createView(), 'disp_number_form' => $dispNumberForm->createView(), 'order_by_form' => $orderByForm->createView(), 'forms' => $forms, 'Category' => $Category, ]; } }
<?php namespace Customize\Repository\Extension; use Eccube\Repository\ProductRepository; use Eccube\Repository\QueryKey; use Eccube\Util\StringUtil; class ProductRepositoryExtension extends ProductRepository { /** * get query builder. * * @param array $searchData * * @return \Doctrine\ORM\QueryBuilder */ // 先ほどのgetQueryBuilderBySearchDataの関数名を書き換え public function customizeGetQueryBuilderBySearchData($searchData) { // 以下は同じ処理 $qb = $this->createQueryBuilder('p') ->andWhere('p.Status = 1'); // ~~省略