[EC-CUBE3]ページャーに複数のエンティティを渡した時のエラーに対応する

リレーションマッピングされてないエンティティをJOINしてページャーに渡すとエラーが表示された。
通常、リレーションマッピングされてないエンティティをJOINした時は下記のような形式で値が返る。

// JOIN例
$qb
   ->addselect('h.hoge_id')
   ->leftJoin('Entity\Hoge', 'h', 'with', 'p.id = h.Product')
;

getResult()を実行した時の値。配列の中にオブジェクトと、指定したカラム(今回の場合はhoge.id)が返る。

array:4 [▼
  0 => array:2 [▼
    0 => Product {#9999 …99}
    "hoge_id" => null
  ]
  1 => array:2 [▶]
  2 => array:2 [▶]
  3 => array:2 [▶]
  4 => array:2 [▶]

ここまでは問題ないが、このクエリの結果をページャーに渡すと下記のエラーが表示される。

Cannot count query which selects two FROM components, cannot make distinction

getResult()でクエリの結果を取得する分には問題ないが、Ec-cubeのページャー(KnpPaginator)では配列の形式ではなく、1つのエンティティを渡さなければいけない。

対応方法

JOIN対象の商品一覧を別クエリで取得。そのあとにwhere in句を使用して検索するようにした。

$qb2 = $this->getEntityManager()->createQueryBuilder();
$qb2
   ->select('h.product_id')
   ->from('Entity\Hoge', 'h')
;
$hoge_items = $qb2->getQuery()->getResult();
$items = [];
// in()に渡すために配列を整形する
foreach ($hoge_items as $v) {
   $items[] = $v['product_id'];
}

$qb
   ->andWhere($qb->expr()->in('p.id', $items));

補足:HIDDENキーワードを指定した時の扱いについて

addSelectにHIDDENキーワードを付与すると、配列の中に「オブジェクト + 要素」ではなく、オブジェクト単体が返ってくる。
下記の例だとJOINした結果のオブジェクトは返ってくるが、HIDDENを指定した値は返り値には含まれない。

$qb
   ->addselect('COUNT(h.id) as HIDDEN hoge_id_count')
   ->leftJoin('Entity\Hoge', 'h', 'with', 'p.id = h.Product')
;

下記のようになる。

array:1 [▼
  0 => Product {#9999 ▶}
]

ただ見かけ上は1つのオブジェクトになっているが、JOINしているという情報は$qb内の joinRootAliases を確認すると見ることが出来る。
ページャーに渡すとこの状態でもエラーになってしまう。

参考
DoctrineのDQLと仲良くなるなる方法【その1】

The QueryBuilder

Subquery in doctrine2 notIN Function

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ten + 2 =

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください