WordPressのサブループでWP_Queryのオブジェクトを使いつつ、ページネーションするハック
WordPressのtemplate内でquery_posts()は非推奨というのは、割と浸透してきたようなのですが、それでも、query_posts()を使う人がいるのは、ページネーション(ページング)をしたいとか、いろいろと一見便利な「副作用」があるからですよね。
メインループの時には、the_posts_pagination()で、手軽にページネーションが表示されるのに、サブループだとうまくいかない。そんなとき、query_posts()を使うとうまくいく……というわけです。
なんで、query_posts()を使うとうまくいくかというと、query_posts()が、$GLOBALS['wp_query']を書き換えるからです。
WordPressは、スーパーグローバル変数のお祭り状態なので、たいへん「らしい」といえば「らしい」です。
短いんで、ちらと、query_posts()をのぞいてみましょう。
function query_posts($query) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($query);
}
これだけです。
で、ページネーションを出力しているget_the_posts_pagination()は、$GLOBALS['wp_query']に依存しているので、当然、$GLOBALS['wp_query']に代入されているオブジェクトを相手にしかしてくれません。
というわけで、サブループで、WP_Query()をnewしつつ、ページネーションするための関数を書いてみます。
これはfunctions.phpに記述します。
/**
* wrapper get_the_posts_pagination and the_posts_pagination
*/
if (
! function_exists('my_get_the_posts_pagination') &&
! function_exists('my_the_posts_pagination')
)
{
function my_get_the_posts_pagination (WP_Query $wp_query_obj, $args = array())
{
$tmp_obj = $GLOBALS['wp_query'];
$GLOBALS['wp_query'] = $wp_query_obj;
$navigation = get_the_posts_pagination($args);
$GLOBALS['wp_query'] = $tmp_obj;
return $navigation;
}
function my_the_posts_pagination (WP_Query $wp_query_obj, $args = array())
{
echo my_get_the_posts_pagination($wp_query_obj, $args);
}
}
で、
$my_query = WP_Query($args);
とかしたら、
my_the_posts_pagination($query);
で、当該ループのページネーションを取得できます。
原理的にはメインクエリを汚していないので、wp_reset_query()もwp_reset_postdata()も不要です。
余談
WordPressでは、$postsや$postや$wp_queryが、スーパーグローバルなんですが、うっかり、
foreach ($posts as $post): endforeach;
みたいなコードを書いちゃうと、スーパーグローバルを壊しちゃうんですね。
気をつけましょう。

