web-dev-qa-db-ja.com

WPカテゴリ名によるクエリグループ/順序

カテゴリ別に分類されたカスタム投稿タイプのリストを表示する必要がありますが、これに加えて、各カスタム投稿はメタ値にリンクされています(この例では "TEST1"のカスタムメタ値があるとします)。

基本的に、私の目標は、すべてのカスタム投稿のカテゴリ別に分類されたリストをコード「TEST1」で表示することです。現在これを行っている方法は、すべてのカテゴリを私のカスタム投稿タイプにリンクさせ(空を無視)、次に各カテゴリをループ処理して「TEST1」のコードを持つすべての投稿を取得することです。

今ではこれは素晴らしいです、それはうまく動作しますが、それは非常に非効率的です。現時点ではこれは問題ではありませんが、カテゴリの数が時間の経過とともに増加しても規模がそれほど拡大されないことがあります。つまり、反復ごとにDBヒットが発生します(およびpostメタテーブルに結合します)。

私はウェブをよく見てきましたが、何かを見つけることができませんでしたが、カテゴリー化されたカテゴリー化された「TEST1」のカスタムメタ値を持つすべての投稿を返すWP_Query呼び出しを実行できるかどうか疑問に思いましたか?これははるかに効率的です(基本的に1 DBヒットと思います)。誰かがここで何かアドバイスができれば私は本当にありがたいです、それが不可能であれば私はこれを達成するための私の唯一の方法が私のプラグイン内からデータベースへの直接問い合わせを行うことであると思います。プラグインを扱うときに助言します)。

2
hdougie

あなたがこれを行うことができるいくつかの方法があります。

最も簡単なのは、投稿と用語のすべてを取得し、次にarray_filterマジックを使用してものをグループ化することです。簡単な例(PHP 5.3以降でのみ動作します):

<?php
$terms = get_terms('your_taxonomy');

$term_ids = array_map(function($t) {
    return $t->term_id,
}, $terms);

$posts = get_posts(array(
    'nopaging'      => true,
    'tax_query'     => array(
        array(
            'taxonomy'  => 'category',
            'field'     => 'id',
            'terms'     => $term_ids,
        ),
    ),
    'meta_query'    => array(
        array(
            'key'       => 'TEST1',
            'compare'   => 'EXISTS', // wp 3.5+ only
        )
    ),
));

foreach ($terms as $t) {
    $posts_in_term = array_filter($posts, function($p) use ($t) {
        // has_term likely triggers a DB hit...
        return has_term($t->term_id, 'your_taxonomy', $p);
    });

    // do stuff with $posts_in_term 
}

これはかなり理解しやすいです。あなたはあなたがDBに送ったであろう注文作業の多くを取り、それをPHPアプリ自体の中で行いました。悪くない、確かにあなたがしていたより少ないDBヒット。各カテゴリ名に見出しを付ける必要がある場合は、次の方法では非常に困難になるため、この方法が適しています。

オプション2:get_postsクエリを通常どおりに行いますが、posts_groupbyにフックして用語ID順に並べます。 WP_Tax_Queryクラスで順序付けするためのテーブルのエイリアス/名前を特定するための掘り下げを行う必要があります。これは、指定されたセットに含まれる分類クエリの数に基づいてテーブルのエイリアスを作成します。私たちは1つしか持っていないので、別名はなく、あなたは$wpdb->term_relationships.object_idをgroup byに追加する必要があります。結果はGROUP BY $wpdb->posts.ID, $wpdb->term_relationships.object_idのようになります。

例:

<?php
// our group by callback
function wpse84243_groupby($groupby, $query) {
    global $wpdb;

    return $groupby . ' ' . $wpdb->term_relationships . '.object_id';
}

add_filter('posts_groupby', 'wpse84243_groupby', 10, 2);
$posts = get_posts(array(
    'nopaging'      => true,
    'tax_query'     => array(
        array(
            'taxonomy'  => 'category',
            'field'     => 'id',
            'terms'     => get_terms('category', array('fields' => 'ids')),
        ),
    ),
    'meta_query'    => array(
        array(
            'key'       => 'TEST1',
            'compare'   => 'EXISTS', // wp 3.5+ only
        )
    ),
));

// remove the filter, put things back to normal
remove_filter('posts_groupby', 'wpse84243_groupby', 10, 2);

// do stuff with $posts, they'll be grouped by your taxonomy ID.
1
chrisguitarguy