環境ec-cube 3.0.10
PHP 7.0.10
MySQL 5.5.45
前提・実現したいこと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の指定方法がおかしい可能性が高そうなんですが「じゃあどうすればいい」という方針まで辿りつかず・・。