query_posts と pre_get_posts と WP_Query

WordPressをいじりはじめたころ、「query_posts」で検索すると、

query_postsを捨てよ、pre_get_postsを使おう

というのが見えて、え!?っとなって、 query_postsのページには、

「ひとことで言うと、query_posts() は決して使うべきではありません。」

とまで書いてあるし。

それじゃ、ということで、 query_posts の代わりに pre_get_posts を使えばいいんですな、と調べたら、必ずしも置き換えられるものではない、としってなんじゃそりゃ。となったり。

結論から言うと、query_posts の置き換えは、get_post か、WP_Query を使おう。となるのですが、 じゃ、get_post と、WP_Query どう使い分けるの?とか、 pre_get_posts はなんに使うの?とか、 query_postsと、get_post、WP_Query は記述の仕方が似て非なるもので、覚え直すのが面倒。とか思うわけです。
特にノンプログラマの人には混乱著しいのではと思うのです。 そこで、そこのところをまとめ。

メインクエリの存在を知る

そもそもWordPressが固定ページや投稿のデータをどのタイミングでとってきているか、ということを頭にいれとかないと使い分けできません。
たとえば、とあるカテゴリページを表示させるとします。 すると、はじめにデータベースから「とあるカテゴリ」に該当する投稿を取得して、それをメインクエリとして保管します。

このメインクエリに保管された、投稿のタイトル、本文、日付なんかを、取得した順番に表示させることでカテゴリページが表示されます。

メインクエリを、上書きするのか、しないのか

さて、その上で category.php の中に、query_posts を書き込むとどうなるかというと、はじめに保管したメインクエリをあたらしい条件で書き換える、ということになります。

書き換えてしまう以上、「とあるカテゴリ」の一覧だったメインクエリは消えてしまいます。
カテゴリページにquery_postsを使って、「おすすめ記事」を3件とか表示させたとすると、メインクエリは「とあるカテゴリ」ではなく、「おすすめ記事」に書き換わってしまう。

その後でページングの処理などにメインクエリが利用された場合、「おすすめ記事」の一覧の内容で処理されて、へんなことになっちゃうぞ! というのが、query_postsを使うな、WP_Queryやget_postsを使え、という理由なわけです。

とかいいつつも、wp_reset_query を使えば、もとのメインクエリ「とあるカテゴリ」に戻すことはできるので、query_posts を使った後にはwp_reset_query で後始末することを徹底すれば問題ないのでは。 とも思っていたのですが、他のプラグインの影響を受けやすいとか、トラブルのたねになりかね無いようなので、やっぱり基本は使わないほうが良さそう。
そもそも、query_posts でやりたいことは、WP_Queryで出来るわけですから。

メインクエリそのものを変えたいとき

以上は、メインクエリとは別の一覧を表示させたいときなんかの場合でしたが、そもそも、カテゴリページの並び方を変えてしまいたい、と考えたとします。
そうすると、query_posts はメインクエリを書き換えますから、願ったり叶ったりとおもうのですが、そうとも言えないようです。

たとえば、カテゴリページを表示しようとするとき、
・メインクエリを取得するために、データベースにアクセスします。(1回目)
・そのあとで、query_postsメソッドで、再度データベースにアクセスします。(2回目)

と、2回データベースにアクセスすることになります。(しかも1回目はムダ!)
だったら、1回目の時に順番を変えておけばいいじゃない。とうのが、pre_get_postsフックです。

pre_get_posts を使えば、1回目のメインクエリ条件そのものを変更することが出来るので、query_posts ではなく、pre_get_posts を使うべきだ。というわけです。
また、通常 pre_get_posts は function.php に書き込むので、query_postsのように、テンプレートごとにコードを書かなくてもいい、というメリットもあります。

ということで、基本的に WP_Query クラス pre_get_posts フック この二つを使えば、やりたいことは出来そうことでOKではないでしょうか。

で、 get_posts メソッド(投稿用) get_pages メソッド(固定ページ用) は、というと、WP_Query の機能限定版と思ってます。
というのも、(query_postsもそうですが)get_postsも、get_pagesも、内部で WP_Query 呼び出してるし、別々に使い方覚えなくてもいいんじゃまいか。 こちらの記事がとても参考になりました。

WordPress ループ&クエリーのモヤモヤを解消しよう!
12月25日まで毎日ブログをつないでいく WordPress Advent Calendar、12日目担当 福山カズヒデ (@kzxtreme) です、こんにちは。aka aus Cothodyntomo(@aka_aus_pd)さんの「錆びたブログをまた動かすときに必要な事柄」からバトンをいただきました!WordPr...
タイトルとURLをコピーしました