WordPressでquery_postsを使ってはいけない

WordPressでquery_postsを使ってはいけない PHP
// TOPページの記事一覧(index.php)で特定のカテゴリのみ表示
<?php 
query_posts('cat=カテゴリーID'); 
// ループ
if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();
        // 処理を記述
    }
}
?>

WordPressで検索条件を絞る方法をググると頻繁に以下のような方法が出てきます。

しかしquery_postsはとても危険な方法なので使用しないようにしましょう。

query_postsとは

query_postsは/wp-includes/query.phpにコードがあります。

/**
 * Sets up The Loop with query parameters.
 *
 * Note: This function will completely override the main query and isn't intended for use
 * by plugins or themes. Its overly-simplistic approach to modifying the main query can be
 * problematic and should be avoided wherever possible. In most cases, there are better,
 * more performant options for modifying the main query such as via the {@see 'pre_get_posts'}
 * action within WP_Query.
 *
 * This must not be used within the WordPress Loop.
 *
 * @since 1.5.0
 *
 * @global WP_Query $wp_query WordPress Query object.
 *
 * @param array|string $query Array or string of WP_Query arguments.
 * @return WP_Post[]|int[] Array of post objects or post IDs.
 */
function query_posts( $query ) {
	$GLOBALS['wp_query'] = new WP_Query();
	return $GLOBALS['wp_query']->query( $query );
}

翻訳すると以下のようになります。

注 1: この関数はプラグインまたはテーマの中で使われることを想定されていません。後ほど出てくる説明にあるように、メインクエリーを変更するにはパフォーマンス面でも優れたより良いオプションが存在します。

注 2: query_posts() はページ内のメインクエリーを書き換え、新しいクエリーのインスタンスと置き換えるために使う関数としては過度に単純化され、問題が発生しやすい方法です。非効率的で(SQL クエリを再実行します)、一部の状況では適切に実行することもできません(特にページング処理)。モダンな WordPress コードではもっと安定したメソッドを使うべきです。例えばpre_get_posts フックを使った方法などです。ひとことで言うと、query_posts() は決して使うべきではありません。

https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/query_posts

query_posts()の問題は大きくいうと2つあります。

問題点
  • パフォーマンスの低下
  • エラーが発生しやすい

パフォーマンスの低下

query_posts() はグローバル変数であるため、new WP_Query();されると再度データベースへのアクセスが走るため、その分パフォーマンスが低下します。

エラーが発生しやすい

query_posts() はグローバル変数であるため、他のページでも参照されている可能性があるため、new WP_Query();で初期化されると、思わぬエラーが発生する可能性があります。

替わりの方法を紹介します。

pre_get_postsを使う

このフックはクエリ変数オブジェクトの生成後、実際にクエリが実行される前に呼び出されます。

query_posts()と違い、事前にセットされていた検索条件がリセットされることはありませんし、クエリ実行前に呼び出されますので、パフォーマンスも向上します。

記事の冒頭で紹介したようにカテゴリーを絞り込む場合、以下のようにfunctions.phpに記載します。

「メインクエリ」は、WordPressが現在のページのコンテンツを作成するために使用するものです。

function filter_category( $query ) {
    // 管理画面や、メインクエリ以外の処理に影響を及ぼさないように
    if ( is_admin() || ! $query->is_main_query() ){
        return;
    }

    if ( $query->is_home() ) {
        $query->set( 'cat', 'カテゴリーID' );
    }
}
add_action( 'pre_get_posts', 'filter_category' );

pre_get_postsは管理画面やメインページ以外でもフックされてしまいますので、最初に制御しています。

タイトルとURLをコピーしました