アーカイブテンプレートでquery_postsを使ったらページ送りで嵌った!という話。

最近カスタム投稿タイプやら、マルチサイトでのブログ一覧をいじくることがそこそこあったのですが、ちょっと注意したいことがあったのでまとめ。

query_postsとは

テンプレートタグ/query posts – WordPress Codex 日本語版

まぁ、おおざっぱにいえば、WordPressのそのページで使われているループを強制的に上書きしてしまう機能です。通常はURLを解釈して、それを元に記事を探してくるのですが、それを完全に無視します。

“トップページとかでお知らせのタイトルを5件だけ表示する”みたいなときに使うことが多いと思いますが、カスタムページテンプレートで何かの記事一覧を出したり、なんて使い方をすることもたまにあったり。

1ページ目と内容が変わらない。

よくあるトラブルその1ですね。URLには”paged/2″とか書いてあるのですが、query_postsで再設定してしまっているので、うまくいきません。

解決としては、query_postsに「今何ページ目?」という情報を与えてあげればよいので、

だとか

だとかしてあげればOKです。

ページが見つかりませんでしたと表示される。

今回の現象です。なぜか404になってしまいます。
上記の設定ができているのに、うまくいかないということがありました。

WordPressのテンプレート選択は、URLを解釈して読み込まれるわけですが、アーカイブページでは、最後のページが”/page/10″などの場合、”/page/11″だとかはNot Found扱いになり、404.phpが読み込まれます。これはカテゴリーでもカスタム投稿アーカイブでも同様です。

なので、query_postsをarchive.phpなどに書いていたとしても、archive.phpが読み込まれる前にページが存在しないという判定になります。

たとえば投稿が100件あって、WordPressの設定では1ページ当たりの表示件数を10件としている場合に、query_postsで5件しか表示しないようにしていると、11ページ目が存在するかしないかの判定は、WordPressの設定を使うので、すべての投稿が表示されていないのに、Not Foundとなってしまいます。

解決法1

archive.phpとかarchive-post_type.phpとかcategory.phpだとかで、メインのループを上書きしない。

テンプレートがちゃんと提供されているので、それをちゃんと素直に使いましょう。ということです。

解決法2

ただしそういうわけにもいかないときもあるとは思いますし、カスタム投稿タイプごとに表示件数もデザインも変えたい!ということはあるかと思います。

そんなときの対処法ですが、
WordPressの設定->表示設定->1ページに表示する最大投稿数をquery_postsで設定している値より小さくするとちゃんと全部の記事が表示されます。

この場合は、テンプレートにもしっかり、ページが見つからなかった時の表示をしっかり記入しておきましょう。

まとめ

URL から得られたクエリを変更することはトラブルの元になります。条件分岐タグ のようなページの判定を組み合わせることで、URL を一切変えることなく投稿 の見せ方をカスタマイズすることができます。

query_posts() 関数はメインの WordPress ループだけを変更するためのものです。新たなループを作るためのものではありません。メインループの他にループが必要な場合は、get_posts() を使ってください。メインループの他で query_posts() を使用すると、メインループが不正な状態になり期待する結果が得られません。

query_posts() 関数はページのメインクエリを上書きし、置き換えます。他の目的で使用しないでください。

query_posts() 関数は新しい WP_Query オブジェクトを作成し、グローバル wp_query 変数に割り当てます。get_posts() 関数は、グローバルエリアをまったく上書きすることなく新しい WP_Query オブジェクトを作成します。

とCodexにも記載されております。query_postsは便利ですが、使い方を間違えると面倒だったりします。用法・用量を守って正しく使いましょう!