pre_get_postsのアクションフックを使う際に配列でクエリを書き換える
なんらかの理由でメインループをいじりたいときに、pre_get_postsのアクションフックを使うが、WP_Queryの引数とかにあるような配列を使ってクエリを書き換える方法が探してもなかなか出てこなかった。
ソースコードと英語版コーデックスを読んで、それを行うparse_query()を見つけたので書き残しておく。
通常、pre_get_postsを使う際に追加の条件を指定するときには以下のようなやり方で行うが、
function theme_rewrite_query( $query ) { if ( is_category( 0 ) ) { $query->set( 'cat', '1,2' ); $query->set( 'posts_per_page', 50 ); } } add_action( 'pre_get_posts', 'theme_rewrite_query' );
カテゴリや固定ページなど元のクエリの情報ありきで、その一部を書き換えるときには便利ではあるものの、このやり方だとクエリそのものの情報をまるっとごりっと変えたい場合にとても不便。
クエリのパラメータを全部変えるとかまどろっこしくてやってられん。
こうじゃなくてクエリの指定の形式は、いつもループを指定するときに使っている
$args = array( 'cat' => array( '1', '2' ), 'posts_per_page' => 50, );
こういった感じの配列を直接指定したい。
そんなときにはpre_get_postsをフックした際に、parse_query()のメソッドを利用して以下のような形でクエリの条件を指定する。
function theme_rewrite_query( $query ) { // 念のためにクエリの書き換え前のis系の条件を退避しておく $is_category = $query->is_category( 0 ); if ( $query->is_category( 0 ) ) { $args = array( 'cat' => array( '1', '2' ), 'posts_per_page' => 50, ); // クエリを再設定 ※この時点で$argsで指定した以外の$queryの値は全てデフォ値になる $query->parse_query( $args ); // このpre_get_postsの条件に準ずるクエリに応じて必要な情報を再セットする $query->is_front_page = false; $query->is_home = false; $query->is_xxx = true; } } add_action( 'pre_get_posts', 'theme_rewrite_query' );
parse_query()を使う際の注意点として、set()メソッドとは違い、追記するのではなく完全な書き換えとなるということ。
つまり、よく使うis系の関数とかとかがparse_query()でクエリを書き換えるページで初期化されるので、その点だけは必ず留意する必要がある。
まぁ、上記のコードはあくまでサンプルであるため条件にカテゴリを指定していたりと、かなり適当。
上記のコードで書いた条件の場合は別にset()でも全然行ける。というか絶対にそっちのほうがいい。
実際の使い所としては、WordPress上のSQLで、特殊な条件で記事データ等の配列オブジェクトをすでに生成しており、更に配列オブジェクトに条件を加えたい場合とかに有用。
自分は今回は必要に迫られたので使ったが、使い所が見極められないうちは安易に組み込まないほうがいいかもしれない。
まぁこういうやり方もあるということで。