web-dev-qa-db-ja.com

カスタム分類法から特定の用語を表示し、「親」用語を除外しますか?

私は(他の多くのカスタム投稿タイプがそうであるように) 'カテゴリ'および 'タグ'と呼ばれるカスタム分類法を持つカスタム投稿タイプ "mycustom_products"(階層型)を持っています。私のカスタムカテゴリは "myprod_category"(階層型)と呼ばれ、私のタグ分類は "product_tag"と呼ばれます((階層型ではない)。

特定の商品カテゴリにのみ対応する商品タグのリストを表示したいです。

たとえば、 "石鹸"や "ローション"のような商品カテゴリでは、 "ブルーベリー"や "ラベンダー"(香り)と呼ばれるタグがあるかもしれませんが、 "ジュエリー"は "シルバー"や "ゴールド"のようなタグがあります。 「香り」のみのタグ(「石鹸」と「ローション」のカテゴリーにのみ対応するものになります。「ジュエリー」のタグを含めたくない)のリストを作成できるようにしたいです。そのため、それらのカテゴリに入力された商品に使用されたタグはすべて含まれ、他のカテゴリに使用されたタグは含まれません。

もちろん、すべてをテーマにハードコーディングすることもできますが、クライアントがさらにタグを追加する場合は、すべてを入力し直してコードを書き直す必要があります。それを避けたいのです。

すべてのタグを一覧表示するために<?php wp_tag_cloud( array( 'taxonomy' => 'product_tag', format => 'list' ) ); ?>を使用しようとしましたが、「商品カテゴリ」全体が表示されないようにするためのEXCLUDE引数を取得できないようです。 tag_IDを使用してそれを実行できるように思えますが、それは面倒で、それらをテーマにハードコーディングして新しいタグが追加されるたびに更新しなければならないことに戻ります。

カテゴリを除外するために使用できるフィルタなどはありますか。または、この方法でタグを一覧表示するためのより良い方法があります。ありがとうございます。

2
RodeoRamsey

あなたがたくさんの製品を持っているなら、おそらくカスタムSQLクエリがより良いオプションです。

どちらにしてもそのルートをたどることをお勧めします。カスタムクエリは 'icky'になるかもしれませんが、ほとんどの場合、リソースを軽くし、少し速くなることがあります*。

私は、ほとんどの作業を実行する関数を書きましたが、他のシナリオでも役に立つことがあります(関係が明示的ではないことを暗示するために「ソフト」という言葉を使いました)。

/**
 * Get terms that are indirectly associated with others through the posts they
 * are attached to.
 * 
 * @see http://codex.wordpress.org/Function_Reference/WP_Query#Taxonomy_Parameters
 * @link http://wordpress.stackexchange.com/questions/16393/
 * 
 * @param string|array $taxonomy The taxonomy(s) of the terms you wish to obtain.
 * @param array $tax_query A tax query for the posts you want to make the association with.
 * @return array Array of term IDs.
 */
function get_terms_soft_associated( $taxonomy, $tax_query  )
{
    global $wpdb;

    // so you can pass a single tax query rather than wasted nested array
    if ( isset( $tax_query['taxonomy'] ) )
        $tax_query = array( $tax_query );

    $tax = new WP_Tax_Query( $tax_query );
    extract( $tax->get_sql( $wpdb->posts, 'ID' ) );

    if ( empty( $join ) || ( !$posts = $wpdb->get_col( "SELECT $wpdb->posts.ID FROM $wpdb->posts $join WHERE 1=1 $where" ) ) )
        return array();

    $taxonomy = implode( "','", array_map( 'esc_sql', ( array ) $taxonomy ) );
    $posts = implode( ',', wp_parse_id_list( $posts ) );

    return $wpdb->get_col(
        "SELECT DISTINCT t.term_id FROM $wpdb->terms AS t " .
        "INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id " .
        "INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id " .
        "WHERE tt.taxonomy IN('$taxonomy') AND tr.object_id IN($posts)"
    );
}

$tax_queryの詳細については、 税務照会に関するコーデックス を参照してください。これは、別の分類法のためにすべての用語を収集するための逆引き参照を行う前に、投稿をフィルタリングするために使用しているクエリです。

今解決策へ。

// suggestion 1 - for a single post
$product_cats = get_the_terms( get_the_ID(), 'myprod_category' );

// suggestion 2 - for a product category archive
$product_cats = get_queried_object_id();

// suggestion 3 - for all posts on the current page of an archive
foreach( $wp_query->posts as $_post ) {
    $_product_cats = get_the_terms( $_post->ID, 'myprod_category' );
    foreach ( $_product_cats as $_product_cat )
        $product_cats[] = $_product_cat->term_id;
}

// now get the 'associated' tag IDs
$product_assoc_tags = get_term_soft_association( 'product_tag', array(
    'taxonomy' => 'myprod_category',
    'field'    => 'term_id',
    'terms'    => $product_cats
) );

wp_tag_cloud( array( 'taxonomy' => 'product_tag', 'include' => $product_assoc_tags ) );

あなたの状況やあなたが結果に影響を及ぼしたい投稿に応じて、提案は後で照会するためにすべての製品カテゴリをつかむ方法の例であることに注意してください(提案の1つだけを使うか、あなた自身!)。

期待どおりに機能していないと思われる場合は、 を使用してください の場合、関数の2番目の引数について税のクエリを微調整するだけで済みます。

*脚注:ネイティブ投稿クエリはすべての投稿データを引き込みますが、IDを操作するだけで済みます。あなたがいつでも手助けできるところでメモリを節約すること、そして@Danielが言っているように、私たちがたくさんの投稿を話しているのなら、私たちもたくさんのメモリを話しています。

また、すぐに使用できる条件の下では、get_terms()get_posts()のような関数を使用した場合よりもはるかに少ないデータベースクエリと処理しか使用していないと早く言います。

5
TheDeadMedic

私があなたを正しく理解すれば、直接的な選択肢はないと思います。

必要なカテゴリ内のすべての商品をクエリし、それらのレコードを繰り返し、各商品のタグを取得します。あなたがたくさんの製品を持っているならば、これは遅いでしょう。

似たようなもの(これは通常のカテゴリ/タグ用です。カスタムの分類法に変更する必要があります)

    $posts = get_posts("cat=5&numberposts=-1");
$tags = Array();
foreach ($posts as $ipost){
    $posttags = get_the_tags($ipost->ID);
    foreach ($posttags as $posttag){
        if (!in_array($posttag->term_id, $tags)){
            array_Push($tags, $posttag->term_id);

        }
    }
}

これで、探しているタグの一意のIDが$ tagsに入りました。

あなたがたくさんの製品を持っているなら、おそらくカスタムSQLクエリがより良いオプションです。

1
MZAweb