WP_Queryのメインループは$wp_queryインスタンスからメソッドを実行し該当する投稿データを取得しますが、サブループ(カスタムループ)を作る場合には別途$wp_query2のようなインスタンスを生成する必要があります。
-
-
インドネシアのIT業界|市場動向・セキュリティ課題・日系企業の戦略
インドネシアのIT業界はインターネット技術の発展により急速に成長している。インドネシアでは違法コピーが多く、KMS認証クラックがマルウェアの標的になりやすい。インドネシアのサイバー攻撃は元社員による怨恨が原因であることが多い。
続きを見る
この記事でわかること
- WP_Queryクラスを使用してカスタムループを作成できる。
- query_posts関数はテンプレートタグとして使用されることを想定していない。
- get_posts関数はWP_Queryクラス内のメソッドとは異なる。
- pre_get_postsフックを使用してメインクエリをカスタマイズできる。
- WP_Queryクラスのインスタンスを生成して独自のクエリを実行できる。
WPクラスとWP_Queryクラス
URLからクエリを特定し、条件分岐タグを使えるための値をセットして、wp_postsテーブルなどから必要な投稿データをグローバル変数$postsに格納する3つの処理は、コンテンツを表示するループの中で使われる処理です。
$wp、$wp_the_query、$wp_queryなどのクラスのオブジェクトは、wp-settings.phpの中で実体化され、スーパーグローバル変数$GLOBALSに格納されています。
-
-
WordPressの起動2|読み込まれるコアファイルの順番
WordPressの起動時に読み込まれるコアファイルの順番を理解できる。index.phpがWordPressのエントリーポイントとして機能する。wp-config.phpはWordPressのインストール時に自動生成される環境設定フ…
続きを見る
- wp()
- $wp->main()
- ----$wp->parse_request():①URLをパース(分析)しクエリを特定
- ----$wp->query_posts()
- --------$wp_query->query()
- ------------$wp_query->get_posts():③投稿データを$posts配列に格納
- ----------------$wp_query->parse_query():②条件分岐タグで使用されるすべてのis_変数を設定
<?php if( is_single()): //①③URLから分岐条件にtureかfalseがセットされている?>
<?php
if(have_posts()):
while(have_posts()): the_post(); //②必要なデータが格納される
?>
<h2><?php the_title(); ?></h2>
<?php the_content(); ?>
<?php
endwhile;
endif;
?>
<?php endif; //is_single()?>
query_posts関数とget_posts関数
ややこしいですがWP_Queryクラス内でグローバル変数$postsに投稿データを格納するメソッドもget_posts()ですが、別モノですから要注意。
このテンプレートタグであるget_posts()のほうが、WP_Queryからメインクエリとは別のクエリを生成していることから、カスタムクエリでのデータ取得にはget_query()テンプレートタグが使われてきましたが、2016年当時は以下のようにWP_Queryクラスからカスタムループ用クエリを使うためのインスタンスを生成して使うのが主流です。
つまりquery_posts関数はテンプレートタグ(テンプレートの中で使う関数)ではないわけで、処理の実態はWP_Queryクラス内のメインクエリ取得のための関数です。
一方でget_posts関数はwp-includes/post.phpで以下のように定義されています。
上記のようにquery_posts関数はメインクエリを取得するための関数でありwp-includes/query.php内に以下のように定義されていますが、Codexには「この関数はプラグインまたはテーマの中で使われることを想定されていません。」と書いてあります。
function query_posts($query) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($query);
}
function get_posts( $args = null ) {
$defaults = array(
'numberposts' => 5,
'category' => 0, 'orderby' => 'date',
'order' => 'DESC', 'include' => array(),
'exclude' => array(), 'meta_key' => '',
'meta_value' =>'', 'post_type' => 'post',
'suppress_filters' => true
);
$r = wp_parse_args( $args, $defaults );
if ( empty( $r['post_status'] ) )
$r['post_status'] = ( 'attachment' == $r['post_type'] ) ? 'inherit' : 'publish';
if ( ! empty($r['numberposts']) && empty($r['posts_per_page']) )
$r['posts_per_page'] = $r['numberposts'];
if ( ! empty($r['category']) )
$r['cat'] = $r['category'];
if ( ! empty($r['include']) ) {
$incposts = wp_parse_id_list( $r['include'] );
$r['posts_per_page'] = count($incposts); // only the number of posts included
$r['post__in'] = $incposts;
} elseif ( ! empty($r['exclude']) )
$r['post__not_in'] = wp_parse_id_list( $r['exclude'] );
$r['ignore_sticky_posts'] = true;
$r['no_found_rows'] = true;
$get_posts = new WP_Query;
return $get_posts->query($r);
}
カスタムループ作成はWP_Queryクラスで
いつものWordPressループを$wp_query2のメソッドとして実行します。
WordPressのメインループは、WP_Queryクラスの$wp_queryインスタンスからメソッドを実行し、適切な投稿データを取得しますが、メインループ以外で独自の条件でクエリを実行する場合は、$wp_query2みたいに別途インスタンスを生成する必要があります。
<?php
//WP_Queryクラスの引数を連想配列$argsにセット
$args=array(
'post_type' => 'post', //投稿
'post_per_page'=>3 //取得件数3
);
//WP_Queryクラスからインスタンス$wp_query2を生成
$wp_query2=new WP_Query($args);
?>
<?php
if ( $wp_query2->have_posts() ) {
while ( $wp_query2->have_posts() ) {
$wp_query2->the_post();
}
}
?>
<?php
endwhile;
endif;
?>
メインループの変更はpre_get_postsフックで
プラグイン関数ではWP_Queryのパラメータを配列オブジェクト$queryとして受け取り、setメソッドで値を書き換えます。
functions.php内で、プラグイン関数とpre_get_postsフックをadd_action関数でマッピングしてあげれば、メインクエリを操作できます。
投稿を取得するクエリのコアであるget_postsメソッドの中で、$this->parse_query()を実行した後に、pre_get_postsというアクションフックが仕込んであり、WP_Queryのパラメータを配列引数array( &$this )でプラグイン側に送りますので、プラグイン関数側で$queryという配列型オブジェクトとして受け取り、パラメータを書き換えることで、メインクエリの動きを調整します。
public function get_posts() {
global $wpdb;
$this->parse_query(); //条件分岐タグで使用するis_変数への値をセット
do_action_ref_array( 'pre_get_posts', array( &$this ) ); //アクションフック
//省略
return $this->posts;
}
add_action('pre_get_posts', 'pre_get_posts_map');
function pre_get_posts_map($query){
$query->set('posts_per_page', 3);
}
- $query->set('パラメータ名', '値');
よくある質問|WP_Queryクラスのカスタムループ
本稿の内容に沿って、繰り返し出る問いを短く整理します。
WP_Queryクラスでカスタムループを作成するにはどうすれば良いですか?
WP_Queryクラスでカスタムループを作成するには、新しいインスタンスを生成する必要があります。例えば、$wp_query2のようなインスタンスを生成し、必要な引数を設定してクエリを実行します。これにより、メインループとは別の条件で投稿データを取得できます。
query_posts関数とget_posts関数の違いは何ですか?
query_posts関数はWP_Queryクラス内でメインクエリを取得するための関数で、テンプレートタグとしては使用されません。一方、get_posts関数はテンプレートタグであり、WP_Queryからメインクエリとは別のクエリを生成するために使われます。
pre_get_postsフックを使ってメインクエリを変更する方法は?
pre_get_postsフックを使うことで、メインクエリのパラメータを変更できます。functions.php内でadd_action関数を使ってフックを設定し、プラグイン関数で$queryオブジェクトのパラメータをsetメソッドで書き換えることで、クエリの動作を調整します。