SlideShare a Scribd company logo
これからの
by @HissyNC / WordBench Kobe Group
pre_get_posts: What's the Right Way to Use?
pre_get_posts
の話をしよう
1
query_posts非推奨?
『query_postsを捨てよ、pre_get_postsを
使おう』というブログ記事を公開したとこ
ろ、はてブなどでバズる。「いつの間にこ
んなことになっていたんだよ…」「非推奨
だなんて!いますぐ直さなきゃ!」「急に
言われても困る」「query_posts使いまく
ってたぜマジかよ…」「初心者にこの説明
はキツイでしょ」等々の意見が噴出。
2
pre_get_postsとは何か?
結局、Codexのquery_postsのページに非
推奨の文字が入ったのは一時的なもので、
その後表現が修正され、「query_postsの
代わりにpre_get_postsフィルターを使う
ことを強く推奨する」となった。ではなぜ
数多のWordPress本でも紹介されている
query_postsが推奨されないのだろうか。
pre_get_postsフィルターとは何なのか。
3
まず
テンプレート
とは何か
4
データベースから
目的のデータを
取得して
表示するためのもの
5
ではない
6
テンプレートとは
表示するデータを
整形する
ためのもの
7
データを取得する
目的には
本来使わない
8
どんなデータを
取得するかを
決定するのは
9
URL
10
?p=1
?cat=1
?cat=1&post_type=book&paged=2
クエリー・ストリングという
$query_string
11
URLで
どのデータを取得
するかが決まる
どんな処理を行う
かが決まる
12
ほかのCMS
でも同じ
13
URLがページの
内容を表している
=
インターネットの
基本的な概念
14
ここで疑問
15
Webページには
たくさんのデータ
が表示されており
各ページで共通の
ものもある
16
たとえば
サイドバーに
新着記事を5件表示
URLとは関係なく
どのページにもある
17
記事の下に
関連記事を5件表示
URLとは間接的に関係
があるが
直接示しているもの
ではない
18
これらを
サブクエリー
と呼ぶ
19
?p=1
?cat=1
?cat=1&post_type=book&paged=2
クエリー・ストリングと直接対応し
ているデータのことを
20
メインクエリー
と呼ぶ
21
メインクエリー
と
サブクエリー
違いを理解しよう
22
トップページの内容と
してニュースカテゴリ
ーの記事を表示する
メインクエリー
or
サブクエリー?
23
トップページの内容と
してニュースカテゴリ
ーの記事を表示する
メインクエリー
or
サブクエリー?
24
WordPressでは、フロントページ
は新着投稿か、固定ページか、
2択です。CMSとしてはそれだ
け?と違和感がありますが、そう
いう設計ですので、本来特定のカ
テゴリーの記事をトップページで
表示するのはWordPressではでき
ません。get_postsを使うか、ウ
ィジェットを使いましょう
25
query_posts
の
迷宮
26
query_postsとは
本来
メインクエリーを
改変するためのもの
27
http://example.com/?cat=1
28
http://example.com/?cat=1
カテゴリーID が 1
28
http://example.com/?cat=1
have_posts() = 投稿が存在する?
カテゴリーID が 1
28
http://example.com/?cat=1
have_posts() = 投稿が存在する?
カテゴリーID が 1
the_post() = テンプレートタグを有効化
28
http://example.com/?cat=1
have_posts() = 投稿が存在する?
カテゴリーID が 1
the_post() = テンプレートタグを有効化
<a href= <?php the_permalink(); ?> >
<h2>
<?php the_title(); ?></a>
</h2>
28
http://example.com/?cat=1
have_posts() = 投稿が存在する?
カテゴリーID が 1
the_post() = テンプレートタグを有効化
<a href= <?php the_permalink(); ?> >
<h2>
<?php the_title(); ?></a>
</h2>
↓次の投稿へ
have_posts() = 投稿が存在する?
28
カテゴリーを指定している
が、それ以外は?
表示件数(10件?)
並び順(投稿日が新しい順)
投稿タイプ(投稿)
デフォルト設定がある
29
メインクエリーには
デフォルト設定
がある
30
メインクエリーの
デフォルト設定を
変更したい
= query_posts
31
32
?cat=1
32
?cat=1 デフォルト設定
32
?cat=1 デフォルト設定
クエリーストリングの生成
32
?cat=1
条件分岐タグの設定
デフォルト設定
クエリーストリングの生成
32
?cat=1
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
クエリーストリングの生成
32
?cat=1
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
<a href= <?php the_permalink(); ?> >
<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
クエリーストリングの再生成
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
クエリーストリングの再生成
条件分岐タグの再設定
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
クエリーストリングの再生成
条件分岐タグの再設定
データベースから投稿を再取得
32
?cat=1
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
クエリーストリングの再生成
条件分岐タグの再設定
データベースから投稿を再取得
query_posts以前のアレコレが消えてしまった!
32
大丈夫!
戻す手段が
あります
33
wp_reset_query()
query_posts
発動前の状態に戻す
34
query_posts
何が問題なのか?
35
ページ送りが効かない
(頻出)
原因 = $query_string
と結合していない
global $query_string;
query_posts( $query_string .
'&order=ASC' );
36
条件分岐タグの設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
query_posts()以前の条件で
テンプレートが選ばれてしまう
=意図せず404になる
37
条件分岐タグの設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
条件分岐タグの再設定
2回DBから投稿データを取得
=非効率、表示遅速の原因
38
条件分岐タグの設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
条件分岐タグの再設定
条件分岐タグが上書きされる
=混乱のもと
39
条件分岐タグの上書き
と、query_posts()を
サブクエリーの取得に
使ってしまう間違いが
重なるとカオス
40
header.php
footer.php
category.php
is_category() = true
sidebar.phpで
query_posts()を使用
wp_reset_query()
書き忘れ
is_category() = false
テンプレートファイルをま
たいで影響が出る
41
まとめ
42
query_postsは
便利だが、影響範囲が
大きすぎる
43
条件分岐の上書きは
初心者には分かりにくい
44
これからの
推奨される
方法
45
メインクエリー
の改変
=
pre_get_posts
46
サブクエリー
の作成
=
get_posts
47
サブクエリー
の作成
=
get_posts
条件分岐タグが書き換わらない
47
用途によって
使いわけよう
48
メインクエリー
の改変
=
pre_get_posts
49
function 関数( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( クエリーの改変を適用する条件 ) {
$query->set( パラメーター , 値 );
return;
}
}
add_action( 'pre_get_posts', '関数名' );
pre_get_posts基本文法
50
function 関数( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( クエリーの改変を適用する条件 ) {
$query->set( パラメーター , 値 );
return;
}
}
add_action( 'pre_get_posts', '関数名' );
pre_get_posts基本文法
管理画面とメインクエリー以外
には適用しない
51
function 関数( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( クエリーの改変を適用する条件 ) {
$query->set( パラメーター , 値 );
return;
}
}
add_action( 'pre_get_posts', '関数名' );
pre_get_posts基本文法
表示条件を変更したい
ページを絞り込む
52
function 関数( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( クエリーの改変を適用する条件 ) {
$query->set( パラメーター , 値 );
return;
}
}
add_action( 'pre_get_posts', '関数名' );
pre_get_posts基本文法
メインクエリーの
パラメーターを設定
53
function 関数( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( クエリーの改変を適用する条件 ) {
$query->set( パラメーター , 値 );
return;
}
}
add_action( 'pre_get_posts', '関数名' );
pre_get_posts基本文法
関数の名前は
自由につけて良い
54
function 関数( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( クエリーの改変を適用する条件 ) {
処理
return;
}
}
add_action( 'pre_get_posts', '関数名' );
pre_get_posts基本文法
【最重要】
テーマのfunctions.phpに記載する
query_postsの様に
各テンプレートには書かない
55
?cat=1 デフォルト設定
条件分岐タグの設定
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
<a href= <?php the_permalink(); ?> >
<h2>
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
56
?cat=1 デフォルト設定
条件分岐タグの設定
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
56
?cat=1 デフォルト設定
条件分岐タグの設定
have_posts() = 投稿が存在する?
the_post() = テンプレートタグを有効化
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
pre_get_posts フィルター
= クエリーストリングに無い条件の追加
56
function exclude_category_at_home( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( $query->is_home() ) {
$query->set( 'cat', '-1,-1347' );
return;
}
}
add_action( 'pre_get_posts',
'exclude_category_at_home' );
メインページから特定のカテゴリーを除外する
57
function exclude_category_at_home( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( $query->is_home() ) {
$query->set( 'cat', '-1,-1347' );
return;
}
}
add_action( 'pre_get_posts',
'exclude_category_at_home' );
メインページから特定のカテゴリーを除外する
メインページのみに制限
注意:is_home() ではなく
$query->is_home()
58
function exclude_category_at_home( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( $query->is_home() ) {
$query->set( 'cat', '-1,-1347' );
return;
}
}
add_action( 'pre_get_posts',
'exclude_category_at_home' );
メインページから特定のカテゴリーを除外する
$query->set( パラメーター , 値 );
使えるパラメーターはCodexの
関数リファレンス/WP_Queryを参照
59
function search_exclude_cat_1( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( $query->is_search() ) {
$query->set( 'category__not_in', array(1) );
return;
}
}
add_action( 'pre_get_posts',
'search_exclude_cat_1' );
検索結果から特定のカテゴリーを除外する
60
function search_exclude_cat_1( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( $query->is_search() ) {
$query->set( 'category__not_in', array(1) );
return;
}
}
add_action( 'pre_get_posts',
'search_exclude_cat_1' );
検索結果から特定のカテゴリーを除外する
検索結果で
IDが1のカテゴリーを除外
配列で指定することもできる
61
function search_only_post( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( $query->is_search() ) {
$query->set( 'post_type', 'post' );
return;
}
}
add_action( 'pre_get_posts',
'search_only_post' );
検索結果から固定ページを除外(投稿のみ)
62
function search_only_post( $query ) {
if ( is_admin() ¦¦ ! $query->is_main_query() )
return;
if ( $query->is_search() ) {
$query->set( 'post_type', 'post' );
return;
}
}
add_action( 'pre_get_posts',
'search_only_post' );
検索結果から固定ページを除外(投稿のみ)
検索結果のみに制限
Codexのサンプルは$query->is_search
プロパティを見るより関数で書こう
$query->is_search() → ○
63
function set_post_per_page( $query ) {
if ( is_admin() || ! $query->is_main_query() )
return;
if ( $query->is_home() ) {
$query->set( 'posts_per_page', 1 );
return;
}
if ( $query->is_post_type_archive( 'movie' ) ) {
$query->set( 'posts_per_page', 50 );
return;
}
}
add_action( 'pre_get_posts', 'set_post_per_page');
条件にしたがって表示件数を変更
64
function set_post_per_page( $query ) {
if ( is_admin() || ! $query->is_main_query() )
return;
if ( $query->is_home() ) {
$query->set( 'posts_per_page', 1 );
return;
}
if ( $query->is_post_type_archive( 'movie' ) ) {
$query->set( 'posts_per_page', 50 );
return;
}
}
add_action( 'pre_get_posts', 'set_post_per_page');
条件にしたがって表示件数を変更
メインページでは
1件表示
65
function set_post_per_page( $query ) {
if ( is_admin() || ! $query->is_main_query() )
return;
if ( $query->is_home() ) {
$query->set( 'posts_per_page', 1 );
return;
}
if ( $query->is_post_type_archive( 'movie' ) ) {
$query->set( 'posts_per_page', 50 );
return;
}
}
add_action( 'pre_get_posts', 'set_post_per_page');
条件にしたがって表示件数を変更
movie 投稿タイプのアーカイブでは
50件表示
66
注意点
あくまでパラメーターの追加
固定ページをアーカイブに等
根本的に変更するのは厳しい
= サブクエリーを使う
67
注意点
一部の条件分岐は
pre_get_postsのタイミ
ングでは動作しない
例:is_front_page()
68
サブクエリー
の作成
=
get_posts
69
global $post;
$args = array( 'posts_per_page' => 5, 'cat' => 1 );
$myposts = get_posts( $args );
foreach( $myposts as $post ) {
setup_postdata($post);
?>
<h1><?php the_title(); ?></h1>
<?php
}
wp_reset_postdata();
get_posts記述例
70
global $post;
$args = array( 'posts_per_page' => 5, 'cat' => 1 );
$myposts = get_posts( $args );
foreach( $myposts as $post ) {
setup_postdata($post);
?>
<h1><?php the_title(); ?></h1>
<?php
}
wp_reset_postdata();
get_posts記述例
テンプレートタグのセットアップ
テンプレートタグのリセット
71
Codexで get_posts
のサンプルの書き方
が微妙にまちまち
Codexの改善に期待
72
$args = array(
'posts_per_page' => 5,
'offset' => 0,
'cat' => 0,
'orderby' => 'post_date',
'order' => 'DESC',
'post_type' => 'post',
'post_status' => 'publish',
'suppress_filters' => true,
'ignore_sticky_posts' => true,
'no_found_rows' => true
);
WP_Query記述例
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
?>
<h1><?php the_title(); ?></h1>
<?php
}
}
wp_reset_postdata();
上級者向けかも
73
まとめ
74
メインクエリーの変更は
pre_get_posts
サブクエリーの作成は
get_posts (or WP_Query)
使い分ける
75
Thanks!
質問は公式フォーラム
または Twitter: @HissyNC まで
76

More Related Content

これからのpre_get_postsの話をしよう