query_postsはNG!非推奨コードは使わない

以前はよく使われていた query_posts() というWordPressのコードですが、これはメインループを変更するもので、ずっと前から公式でも非推奨とされています。

何年も前に作ったであろうWordPressのサイトではいまだに見かけることも…。query_posts() を修正することでサイトが動かなくなるなら無理に直さなくてもいいかとは思いますが、新規で作成するなら使わないようにしたいコードです。

query_posts とは

query_posts() はページ内のメインクエリを書き換えるために使うWordPressのコードです。

WordPressはそのページに必要な情報を、URLから判断して自動で読み込みます。メインクエリはそのときに読み込まれている情報のこと。
この時に読み込む情報を query_posts() を使って任意のものに変更することができます。

そのエラー query_posts が原因かも?query_posts がNGな理由

query_posts() を使わない方がいい理由は主に2つ。

  • ページ表示速度が遅くなる
  • エラーが起きやすくなる

サイトを作成・運営する上でどちらも起こってほしくないものです。

ページ速度が遅くなる

query_posts() が行う「メインクエリを書き換える」というのは、WordPressが自動的に読み込んだ情報を、またさらに読み直して上書きすること。そしてこの処理は二度手間になっている場合がほとんどです。

データベースを読み直すため、処理がかなり多くなります。それはページの表示速度が遅くなってしまうこととイコールです。

ページの表示速度は速くしたいもの。このコードがあることによって遅くなるなら無くしたいものです。

エラーが起きやすくなる

query_posts() を使うと $wp_query を上書きします。この $wp_query はグローバル変数といい、WordPress全体で使われています。

そのため上書きしてしまうと、$wp_query を参照している関数(条件分岐タグなど)に影響が出ます。
サイドバーやその他共通で投稿一覧を表示している場合に思い通りに表示されないことがあったり、ページネーションがうまく動かなくなるといったこともあります。

コードを記述している箇所だけならまだしも、その他思わぬところに影響を与えてしまうことが大きな問題。エラーの原因が分かりづらくなってしまうのも困りものです。

WordPress.org でも、テーマ内で使用することを想定したコードではなく「使うべきではない」と書かれています。

query_posts によるエラーが発生した時に確認したいこと

非推奨で使わない方がいいとはいえ、既存のサイトではこのコードが使われていることがあります。

query_posts() を使わないように修正したいものですが、それに莫大な労力が必要になってしまうならうまく付き合う方法を考えた方がいいかもしれません。

もし query_posts() の記述があって、うまく表示されない時に見直したいところをあげていきます。

wp_reset_query() がちゃんとあるか確認する

query_posts() のエラーは、メインクエリが上書きされることによる原因が多いです。そのため上書きする箇所を制限して、他の部分には影響を与えないようリセットできているか確認します。

query_posts() を使ったらループの最後に wp_reset_query() が必要です。このコードがあるかどうか確認してみてください。

<?php
  $args = [
    'post_type' => 'post',
    'posts_per_page' => 5,
  ];
  // 投稿の呼び出しに query_posts
  query_posts($args);
  // 投稿ループ
  if (have_posts()): while (have_posts()): the_post();
?>
  <!-- 〜〜〜 投稿の表示・処理 〜〜〜 -->
<?php endwhile ?>
<!-- ループが終わったあと、これがあるか確認 -->
<?php wp_reset_query(); ?>
<?php endif ?>

query_posts でできることは他のコードにある

query_posts() に代わるコードはちゃんとWordPressに用意されています。

メインループかサブループかによって使うコードが変わります。

メインループpre_get_post
サブループWP_Query もしくは get_posts

メインループでは pre_get_posts

メインループの場合、pre_get_posts を使って投稿取得の条件をつけます。pre_get_posts はクエリを取得する前に実行されるアクションフックです。
アクションフックは、「とあるイベントが発生するときに実行する処理を追加するもの」をいいます。「post(投稿)を読み込む前に」「このアクションをしてね」というイメージです。

add_action('postを読み込む前に', 'このアクションをしてね');
//            ↓↓↓                 ↓↓↓
add_action('pre_get_posts', 'newPrePosts');

query_posts にできて pre_get_posts にできないことはなく、同様のことができます。pre_get_posts を使用する時は functions.php に以下のように記述します。

function newPrePosts($query) {
  if (is_admin() || !$query->is_main_query()){
    return;
  }
  if ($query->is_home()) {
    $query->set('post_type', 'post');
    $query->set('posts_per_page', '5');
  }
}
add_action('pre_get_posts', 'newPrePosts');

if文でページを指定、$query->set() でどの投稿を取るか、何件表示させるかなど指定。メインで使用する内容はこれでセットOK。

pre_get_posts を使う際の注意点として、固定ページでは使えないことがあげられます。固定ページでは WP_Query を使用して、表示内容を設定します。

2つ以上の投稿ループ、サブループは WP_Query や get_posts を使用

同一ページに2つ以上の投稿ループを載せたい場合は WP_Queryget_posts といったサブループを使います。
2つとも投稿やページの情報を取得するためのものですが、メインクエリを書き換えることはしません。

WP_Query は「クラス」で get_posts は「テンプレートタグ」という違いがあります。またコードの書き方も異なりますが、「取得できる情報量」も違います。

get_posts は内部で WP_Query を使用し、いろいろな条件を絞り込んで処理を簡単にしているものです。そのため WP_Query の方がいろいろな条件を指定できます。

WP_Query

使い方は query_posts と同じような書き方になります。取得したいデータをセットし、 while (have_posts()): the_post(); で当てはまる記事を表示させます。

<?php
  $args = [
    'post_type' => 'post',
    'posts_per_page' => 5,
  ];
  // 投稿の呼び出しに WP_Query
  $wp_query = new WP_Query($args);
  // 投稿ループ
  if (have_posts()): while (have_posts()): the_post();
?>
<!-- 〜〜〜 投稿の表示 〜〜〜 -->
<?php endwhile ?>
<!-- 投稿データリセット -->
<?php wp_reset_query(); ?>
<?php endif ?>

get_posts

get_posts は取得した情報が配列になっているので、foreach で回します。

<?php
  // 投稿取得情報はWP_Queryと同じように書く
  $args = [
    'post_type' => 'post',
    'posts_per_page' => 5,
  ];
  // 投稿の呼び出しに get_posts
  $new_query = get_posts($args);
  // 投稿ループ
  if ($new_query):
    global $post;
    foreach ($new_query as $post):
      setup_postdata($post);
?>
<!-- 〜〜〜 投稿の表示 〜〜〜 -->
<?php endforeach ?>
<!-- 投稿データリセット -->
<?php wp_reset_query(); ?>
<?php endif ?>

複雑な条件を指定して情報を取得したい場合は、WP_Query を使用、単純にタイトル・コンテンツ・日付などよく使うものなら get_posts でも十分です。

WP_Query の方が幅広く対応できることから、後から仕様変更の可能性が高いものには WP_Query を使った方が書き直しの手間が省きやすく修正しやすいので無難かなとも思います。

カテゴリー : WordPress

タグ :

TOPへ