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

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

ただいまの
回答率

90.50%

  • EC-CUBE

    311questions

    EC-CUBEは、主に日本国内で開発されているECコンテンツ管理システムです。ロックオン社のECKitを元にしてオープンソース化され、商品管理・受注管理・顧客管理・売上集計などECに特化した様々な機能を備えています。

EC-CUBE3.0.10 商品一覧での複数カテゴリ絞り込み repository拡張

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 2,557

Tenchara

score 2

前提・実現したいこと

ec-cube(3.0.10)を使ってECサイトを構築しています。

商品一覧ページでカテゴリAとカテゴリBのAND条件による絞り込み(dtb_productテーブルの"category_id"を最大2つ指定)の実装をしているのですが、詰まってしまったので相談させてください。

もしよければアドバイスをお願いします。

現在の状態

「ec-cube本体は修正しない」という方針のため、プラグインによる実装を選択しました。

ざっくりとですが、以下1〜4の処理を実装して絞り込みは実現できました。

  1. 商品一覧ページに"親category_id"と"子category_id"をGETパラメータで渡すようリンク設置。(formに追加済)
  2. プラグインのproductRepository.phpで上記2を利用したクエリ追加。
  3. serviceProviderでプラグインのproductRepository.phpに記載した処理を参照するよう指定。

しかし、管理画面の商品編集ページをひらくとシステムエラー(ec-cube側のエラー)が発生するようになってしまいました。

そのため、管理画面に影響のないよう修正したいのですが、どのように修正すればよいかの方針が立てられていない状態です。

エラーメッセージ

ec-cube管理画面から参照できる"EC-CUBEログ"

[2016-09-27 12:02:33] eccube.INFO: < 500 [] []
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't0.product_id' in 'where clause' (uncaught exception) at /var/www/html/ecsite/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php line 71 {"exception":"[object] (Doctrine\\DBAL\\Exception\\InvalidFieldNameException(code: 0): An exception occurred while executing 'SELECT t1.product_id AS product_id2, t1.name AS name3, t1.note AS note4, t1.description_list AS description_list5, t1.description_detail AS description_detail6, t1.search_word AS search_word7, t1.free_area AS free_area8, t1.del_flg AS del_flg9, t1.create_date AS create_date10, t1.update_date AS update_date11, t1.creator_id AS creator_id12, t1.status AS status13 FROM dtb_product t1 WHERE t0.product_id = ? AND ((t1.del_flg = 0))' with params [\"8\"]:\n\nSQLSTATE[42S22]: Column not found: 1054 Unknown column 't0.product_id' in 'where clause' at /var/www/html/ecsite/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php:71, Doctrine\\DBAL\\Driver\\PDOException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 't0.product_id' in 'where clause' at /var/www/html/ecsite/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:93, PDOException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 't0.product_id' in 'where clause' at /var/www/html/ecsite/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:91)"} []
[2016-09-27 12:02:33] eccube.CRITICAL: Doctrine\DBAL\Exception\InvalidFieldNameException: An exception occurred while executing 'SELECT t1.product_id AS product_id2, t1.name AS name3, t1.note AS note4, t1.description_list AS description_list5, t1.description_detail AS description_detail6, t1.search_word AS search_word7, t1.free_area AS free_area8, t1.del_flg AS del_flg9, t1.create_date AS create_date10, t1.update_date AS update_date11, t1.creator_id AS creator_id12, t1.status AS status13 FROM dtb_product t1 WHERE t0.product_id = ? AND ((t1.del_flg = 0))' with params ["8"]:


※apacheのエラーログは出力されていませんでした。

該当のソースコード

プライグインのファイル構成

app/
  |- Plugin/
       |- CustomProductList/
            |- config.yml
            |- event.yml
            |- CustomProductListEvent.php
            |- PluginManager.php
            |- Entity/
                 |- Product.php
            |- Repository/
                 |- ProductRepository.php
            |- Resource/
                 |- doctrine/
                      |- Plugin.CustomProductList.Entity.Product.dcm.yml
            |- ServiceProvider/
                 |- CustomProductListServiceProvider.php

config.yml

name: カスタム商品一覧
code: CustomProductList
version: 1.0.0
service:
 - CustomProductListServiceProvider
orm.path:
 - /Resource/doctrine
event: CustomProductListEvent

Entity/product.php

<?php
namespace Plugin\CustomProductList\Entity;

use Eccube\Entity\Product as BaseProduct;

class Product extends BaseProduct
{
    //  継承のみ
}

Repository/ProductRepository.php

<?php
namespace Plugin\CustomProductList\Repository;

use Eccube\Repository\ProductRepository as BaseRepository;
use Eccube\Common\Constant;
use Doctrine\ORM\NoResultException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class ProductRepository extends BaseRepository
{
    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);
                //  複数カテゴリによる絞り込み START
                if (!is_null($searchData['main_category_id']) && is_numeric($searchData['main_category_id'])) {
                    $qb
                        ->innerJoin('p.ProductCategories', 'pct2')
                        ->innerJoin('pct2.Category', 'c2')
                        ->andWhere($qb->expr()->in('pct2.Category', ':MainCategoryId'))
                        ->setParameter('MainCategoryId', $searchData['main_category_id']);
                }
                // 複数カテゴリによる絞り込み END
                $categoryJoin = true;
            }
        }

        // name
        if (isset($searchData['name']) && Str::isNotBlank($searchData['name'])) {
            $keywords = preg_split('/[\s ]+/u', $searchData['name'], -1, PREG_SPLIT_NO_EMPTY);

            foreach ($keywords as $index => $keyword) {
                $key = sprintf('keyword%s', $index);
                $qb
                    ->andWhere(sprintf('p.name LIKE :%s OR p.search_word LIKE :%s', $key, $key))
                    ->setParameter($key, '%' . $keyword . '%');
            }
        }

        // Order By
        // 価格順
        if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == '1') {
            //@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->groupBy('p');
            $qb->orderBy('price02_min', 'ASC');
            // 新着順
        } else if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == '2') {
            $qb->orderBy('p.create_date', 'DESC');
        } else {
            if ($categoryJoin === false) {
                $qb
                    ->leftJoin('p.ProductCategories', 'pct')
                    ->leftJoin('pct.Category', 'c');
            }
            $qb
                ->addOrderBy('p.id', 'DESC');
        }

        return $qb;
    }
}

Resource/doctrine/Plugin.CustomProductList.Entity.Product.dcm.yml

Plugin\CustomProductList\Entity\Product:
    type: entity
    table: dtb_product
    repositoryClass: Plugin\CustomProductList\Repository\ProductRepository

ServiceProvider/CustomProductListServiceProvider.php

<?php
namespace Plugin\CustomProductList\ServiceProvider;

use Eccube\Application;
use Silex\Application as BaseApplication;
use Silex\ServiceProviderInterface;

class CustomProductListServiceProvider implements ServiceProviderInterface
{
    public function register(BaseApplication $app)
    {
        $app['eccube.repository.product'] = $app->share(function () use ($app) {
            $productRepository = $app['orm.em']->getRepository('Plugin\CustomProductList\Entity\Product');
            return $productRepository;
        });
    }

    public function boot(BaseApplication $app)
    {
    }
}

試したこと

ServiceProvider/CustomProductListServiceProvider.php

上記プログラムの"register"の処理をコメントアウト
→ プラグイン側のgetQueryBuilderBySearchDataが読み込まれない。(複数カテゴリ絞り込めない)
→ 管理画面側のエラーはなくなる。

となるので、entityの指定方法がおかしい可能性が高そうなんですが「じゃあどうすればいい」という方針まで辿りつかず・・。

補足情報(言語/FW/ツール等のバージョンなど)

PHP 7.0.10
MySQL 5.5.45
ec-cube 3.0.10

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

まだ回答がついていません

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

  • EC-CUBE

    311questions

    EC-CUBEは、主に日本国内で開発されているECコンテンツ管理システムです。ロックオン社のECKitを元にしてオープンソース化され、商品管理・受注管理・顧客管理・売上集計などECに特化した様々な機能を備えています。