既存テーブルを一方的に参照する拡張テーブルを新規作成した。参照元の既存テーブルのEntityにマッピングを定義しなくても、doctrineのDQLのWITHを使用することでJOINが可能。
$join = new Expr\Join(
Expr\Join::INNER_JOIN, 'Plugin\ProductExtend\Entity\ProductExtend', 'pe', Expr\Join::WITH, 'p = pe.product', null
);
$qb->add('join', array('p' => $join), true);
$qb->innerJoin('Plugin\ProductExtend\Entity\ProductExtend', 'pe', Expr\Join::WITH, 'p.id = pe.product');
$qb->innerJoin('Plugin\ProductExtend\Entity\ProductExtend', 'pe', Expr\Join::WITH, 'p = pe.product');
DQLのJOIN WITH構文を使えば、無用な関係を定義せずにテーブルの結合ができる – http://blog.tai2.net/doctrine-join-with-syntax.html
しかし、マッピングせずに、WITHでJOINすると結果Entityが複数になる。それ自体は問題にならないのだけど、ページャに影響が及ぶらしく、エラーが出る。
Cannot count query which selects two FROM components, cannot make distinction
既存コントローラのpaginate処理を呼び出している箇所を確認したところ、件数を取得するクエリは用意していなかったので、ページャが自動で上手いことしてくれるのだと思う。ただそのためにはEntityが単体である必要があるのだろう。
調べたら確かにそんな話が出てきた。
件数を取得するクエリを別途渡して上げれば解決するらしい。
だけど残念ながらEC-CUBE3.0.12-p1でこの対応をしようとすると既存ソースを改変するしかない。プラグインではコントロールできない。
まず呼び出し前のフックポイントが無い。さらに、ページャ自体がイベントを持っているので、それを利用して無理やりオプションを改変できるかとも思ったが、呼び出し方の都合からリスナーを登録することもできない。別の手段としてページャを継承したクラスを用意しても
呼び出し方を変えないと結局どうしようもない。
結論:既存ソースを修正するしかない。
コントローラを修正するか、エンティティにマッピングを追加するか…。EC-CUBE3はEC-CUBE2よりプラグインでカスタマイズできる範囲が広いそうですが、手が届かない箇所が意外とあるので諦めが必要ですね。
以上!