[Wordpress]Global変数を汚さずにWP_Queryを使って記事を取得

表示している記事とは別に、他の条件を指定して記事を取得したいときがある。Sidebarに閲覧数のRankingを表示させるとか。

get_postsquery_postsが便利だけど、これらはGlobalな$wp_queryを使うので、WP_QueryをInstance化する方法がOfficial Documentでも記載されている。

この方法の注意点は、独自のparameterを追加して、add_filter('posts_where', hoge())する際に引数を指定しないと実行中のquery Objectを取得できない。詳細はadd_filterのOfficial Document(英語)で。

以下はCustom Fieldにviewsというkeyがあるのだけ絞り込むsample

// Create a new instance
$second_query = new WP_Query( 'view_ranking=true' );

// The Loop
while( $second_query->have_posts() ) : $second_query->the_post();
    echo '<li>';
    the_title();
    echo '</li>';
endwhile;

//loop中に使用した$postを$wp_queryからsetし直す
wp_reset_postdata();

//この関数とadd_filterはthemeのfunctions.phpとかに追記しておく
function hook_posts_where($where, $query) {
    global $wpdb;
    $ranking_count = $query->get('view_ranking');
    if (!empty($ranking_count)) {
        $sql = array();
        $sql[] = "SELECT count(*)";
        $sql[] = "FROM $wpdb->postmeta";
        $sql[] = "WHERE post_id = $wpdb->posts.ID";
        $sql[] = "  And meta_key = 'views'";
        $add_sql[] = "(" . implode(" ", $sql) . ") > 0";
    }

    if (!empty($add_sql)) {
        $where .= " And " . implode(" And ", $add_sql);
    }
    return $where;
}
add_filter('posts_where', 'hook_posts_where', 10, 2);

 

< Related Posts >

Wordpress 開発リファレンスのリンク集
[Wordpress]適用されるfilterとactionを表示する
【PHP】オブジェクトと連想配列。相互変換する