リレーションマッピングされてないエンティティを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
を確認すると見ることが出来る。
ページャーに渡すとこの状態でもエラーになってしまう。