fix #3634[要望]BlogControllerにイベント beforeQueryParamsを追加したい要望を解決
@ryuring すみません。 案件でブログindexに他のブログの記事を混ぜたりするのに必要なため、 取り急ぎ、Blogのみプルリクを送っています。 お手数ですが、ご確認の上、マージをお願いします。
@katokaisya クエリの内容を書き換えるには、afterFindを利用します。。
// result に Queryオブジェクトが入る
$result = $evnet->getData('result');
// 条件を書き換える
$result->where(['BlogPosts.blog_content_id' => 2]);
CakePHP3系以降は、find() の第2引数で条件を指定するパターンと、where() 等のメソッドで指定するパターンがあり、前者はあまり推奨されておらず、baserCMSも後者を前提として作成されています。
そのため、beforeFind() のイベントでは、$this->getData('options') には何も入ってこないことの方が多いです。
また、all() や first() を呼び出すまでは、SQLは発行しない仕組みになっており、それまでは、条件等の書き換えが可能な仕組みになっています。
というわけで、afterFind() のタイミングでは、まだSQLが発行されておらず、条件の書き換えが可能です。
@ryuring ModelEventListenerにて、テストしてみました。
blog_content_id が2のBlog記事一覧を呼び出すときに BcBlog.BlogPosts.afterFindで
// result に Queryオブジェクトが入る
$result = $evnet->getData('result');
// 条件を書き換える
$result->where(['BlogPosts.blog_content_id IN' => [1,2]]);
とすると、 blog_content_id が2の記事しか表示されず、
// result に Queryオブジェクトが入る
$result = $evnet->getData('result');
// 条件を書き換える
$result->where(['BlogPosts.blog_content_id' => 1]);
とすると、取得できる記事は0件になります。
結果から判断すると、クエリの内容を書き換えしているのではなく、 条件を追加しているだけのようです。
例)
$result->where(['BlogPosts.blog_content_id IN' => [1,2]]);
の場合、発行されるSQLの「WHERE」は
WHERE (`BlogPosts`.`blog_content_id` IN (:c1,:c2)
AND `BlogPosts`.`status` = :c3
AND (`BlogPosts`.`publish_begin` <= :c4 OR (`BlogPosts`.`publish_begin`) IS NULL)
AND (`BlogPosts`.`publish_end` >= :c5 OR (`BlogPosts`.`publish_end`) IS NULL)
AND `Contents`.`status` = :c6
AND (`Contents`.`publish_begin` <= :c7 OR (`Contents`.`publish_begin`) IS NULL)
AND (`Contents`.`publish_end` >= :c8 OR (`Contents`.`publish_end`) IS NULL)
AND `BlogPosts`.`blog_content_id` = :c9)
ORDER BY BlogPosts.posted DESC, BlogPosts.id DESC LIMIT 10'
こうなり、 blog_content_id が :c1と:c2 のいずれかであり、 AND blog_content_id が :c9 である という条件になり、 :c1のvalue =>1 :c2のvalue =>2 :c9のvalue =>2 のため、 blog_content_idが2の記事しか表示されません。
また、
$result->where(['BlogPosts.blog_content_id' => 1]);
の場合はSQLのwhereは
WHERE (`BlogPosts`.`blog_content_id` = :c1
AND `BlogPosts`.`status` = :c2
AND (`BlogPosts`.`publish_begin` <= :c3 OR (`BlogPosts`.`publish_begin`) IS NULL)
AND (`BlogPosts`.`publish_end` >= :c4 OR (`BlogPosts`.`publish_end`) IS NULL)
AND `Contents`.`status` = :c5
AND (`Contents`.`publish_begin` <= :c6 OR (`Contents`.`publish_begin`) IS NULL)
AND (`Contents`.`publish_end` >= :c7 OR (`Contents`.`publish_end`) IS NULL)
AND `BlogPosts`.`blog_content_id` = :c8)
ORDER BY BlogPosts.posted DESC, BlogPosts.id DESC LIMIT 10'
:c1のvalue =>1 :c8のvalue =>2 のため、blog_content_idが1且つ2の記事を取得しようとして、そんな記事は存在しないので、0件となるようです。
@katokaisya 話がバラけているので こちらでやり取りしましょう。 https://github.com/baserproject/basercms/issues/3634
@katokaisya クエリパラメーターの変更は、initialize 、または、startup でやるべきでは? という話になりましたが、それで対応できそうですか?