Upload
hishikawa-takuro
View
26.944
Download
3
Embed Size (px)
DESCRIPTION
第24回WordBench神戸で話した資料です。
Citation preview
これからの
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>
<?php the_title(); ?></a>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
クエリーストリングの再生成
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
クエリーストリングの再生成
条件分岐タグの再設定
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
query_posts() = 投稿の再取得
クエリーストリングの生成
クエリーストリングの再生成
条件分岐タグの再設定
データベースから投稿を再取得
32
?cat=1
have_posts() = 投稿が存在する?the_post() = テンプレートタグを有効化<h2>
条件分岐タグの設定
デフォルト設定
データベースから投稿を取得
使用するテンプレートの読み込み
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>
<?php the_title(); ?></a>
データベースから投稿を取得
使用するテンプレートの読み込み
クエリーストリングの生成
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