閲覧数:1,580 views
あなたが今、読んでいるカテゴリー:
wordpress
【WordPress】5分でブログのホームにピックアップ記事を表示させる方法という記事を書きました。この記事は使用している関数の説明です。実現方法については前回の記事をみていただければ分かるはずですので、前の記事を参照ください。
でやっている事自体は簡単で
- カスタムフィールドの値で絞り込みを行ったクエリを発行
- あとはサブループで記事を取得する
ということしかやっていません。ではソースについて詳しく見ていきます。
カスタムフィールドの値で絞込みをして記事ループを行う際に使用したコードと関数の説明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php $pickup = array( 'meta_query' => array( array( 'key'=>'my_pickup', 'value'=>'1' ) ) ); $pickup_query = new WP_Query($pickup); ?> <?php while ( $pickup_query->have_posts() ) : $pickup_query->the_post(); ?> ... <?php endwhile; // end of the loop. ?> <?php wp_reset_postdata(); ?> |
meta_queryについて
meta_queryはWP_Queryやquery_postsに渡せるパラメータであり、カスタムフィールドの値で絞込みを可能にするものです。WordPressのコーデックスに記載されています。
meta_query (array) – カスタムフィールドのパラメータ (Version 3.1より利用可能)
key (文字列) – カスタムフィールドキー
value (文字列|array) – カスタブフィールドの値 (Note: Array support is limited to a compare value of ‘IN’, ‘NOT IN’, ‘BETWEEN’, or ‘NOT BETWEEN’)
compare (文字列) – テスト演算子。 使える値は ‘=’, ‘!=’, ‘>’, ‘>=’, ‘<‘, ‘<=’, ‘LIKE’, ‘NOT LIKE’, ‘IN’, ‘NOT IN’, ‘BETWEEN’, ‘NOT BETWEEN’です。デフォルト値は ‘=’です。
type (文字列) – カスタムフィールド投稿タイプ。 使える値は ‘NUMERIC’, ‘BINARY’, ‘CHAR’, ‘DATE’, ‘DATETIME’, ‘DECIMAL’, ‘SIGNED’, ‘TIME’, ‘UNSIGNED’です。 デフォルト値は’CHAR’です。
new WP_Queryについて
次にWP_Queryのインスタンスを生成している箇所についてです。
クエリを書き換えるのはquery_postsじゃないの?と思われた方もいらっしゃるかもしれませんがこれについて説明します。この記事を執筆している時点ではquery_postsでクエリを書き換えるコードは非推奨となっています。
query_posts() はページ内のメインクエリーを書き換え、新しいクエリーのインスタンスと置き換えるために使う関数としては過度に単純化され、問題が発生しやすい方法です。非効率的で(SQL クエリを再実行します)、一部の状況では適切に実行することもできません(特にページング処理)。モダンな WordPress コードではもっと安定したメソッドを使うべきです。例えばpre_get_posts フックを使った方法などです。ひとことで言うと、query_posts() は決して使うべきではありません。
一般的な投稿の取得には、WP_Queryか、get_postsを使ってください。
出典:テンプレートタグ/query posts – WordPress Codex 日本語版
要はメインクエリーを書き換えたのに、wp_reset_queryを呼び忘れる事で不正な動作を起こすこともあれば、本来の使い方ではないよというお話らしいです。
query.php in tags/4.3/src/wp-includes | WordPress Trac
1 2 3 4 |
function query_posts($query) { $GLOBALS['wp_query'] = new WP_Query(); return $GLOBALS['wp_query']->query($query); } |
これがquery_postsの関数の中身です。要はサブクエリを発行したいだけなのに、スーパーグローバルのwp_queryを書換えるなよということみたいです。自分で、WP_Queryのインスタンス作れよということですね。
wp_reset_query() は $wp_query とグローバルな投稿データを元のメインクエリのものに復帰させます。query_posts() をどうしても使わなければならない場合、その後にこの関数を呼び出すべきです。
出典:関数リファレンス/wp reset query – WordPress Codex 日本語版
query_postsはもう使うなといわんばかりの説明なのでもう使いません。メインクエリを修正する場合はpre_get_postsを使うようにと推奨されています。
ですが、今回はメインループの実装をある程度流用した形で、修正するファイルを抑えてサブクエリを発行したかったのでpre_get_postsではなくWP_Queryを使用しました。
the_postはグローバル変数 $postを書き換えてしまう関数である
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/** * Sets up the current post. * * Retrieves the next post, sets up the post, sets the 'in the loop' * property to true. * * @since 1.5.0 * @access public * * @global WP_Post $post */ public function the_post() { global $post; $this->in_the_loop = true; if ( $this->current_post == -1 ) // loop has just started /** * Fires once the loop is started. * * @since 2.0.0 * * @param WP_Query &$this The WP_Query instance (passed by reference). */ do_action_ref_array( 'loop_start', array( &$this ) ); $post = $this->next_post(); $this->setup_postdata( $post ); } |
新しく生成したWP_Queryインスタンスのthe_post()を使用していますが、この関数はグローバル変数の$postを書き換えます。(get_postsを使用した場合はグローバル変数$postは書き換えませんが実装が面倒になります)
ですので、この処理を行った後にグローバル変数の$postを使用した処理に支障が出ないように、最後にwp_reset_postdata()を呼ぶ必要があります。
この関数は、new WP_Query を使って二番目のクエリを実行した後に、メインクエリの $post グローバル変数を復元するために使用します。つまり $post がメインクエリの現在の投稿になります。
やっている事はグローバル変数 $wp_queryのpostでグローバル変数の$postを上書きする関数です。プラグインの動作や自分が実装したコードに影響がないことを保証したければ必ず呼ばなければなりません。
wp_reset_postdataを呼ぶ実行時間も削りたいという方は、処理の途中でグローバル変数の$postに依存していないかを確認した上で、呼ぶか呼ばないかを決めてみたらよいかと思いますが、かなり実装依存のコードになり安全ではないので、おススメしません。
さいごに
今回の方法は記事が沢山増えてくると、データベースにアクセスする回数が増えサーバーに負荷がかかる事が予測されます。このブログが月間6万PVくらいですが、300記事満たないくらいであれば特に問題はないです。
高速なPickup記事の実装を行うのであれば、wp_postmetaを使うのではなく、データベースにピックアップ記事専用のテーブルを作っておいて、そこから情報を引っ張ってくる方が絶対高速です。でもそういうのはアクセスが増えてからやったらいい話です。
やっている事自体は簡単ですので、みなさんも是非色んな方法で実装してみてください!