問題描述

我有 2 個自定義帖子類型’bookmarks’ 和’snippets’ 和共享分類’tag’ 。我可以使用 get_terms() 生成分類學中所有術語的列表,但我無法弄清楚如何將列表限制為帖子類型。我基本上正在尋找的是這樣的:

get_terms(array('taxonomy' => 'tag', 'post_type' => 'snippet'));

有辦法實現嗎?想法非常感謝!

哦,我在 WP 3.1.1

最佳解決方案

這是另一種做一些類似的事情,一個 SQL 查詢:

static public function get_terms_by_post_type( $taxonomies, $post_types ) {

    global $wpdb;

    $query = $wpdb->prepare(
        "SELECT t.*, COUNT(*) from $wpdb->terms AS t
        INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
        INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id
        INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id
        WHERE p.post_type IN('%s') AND tt.taxonomy IN('%s')
        GROUP BY t.term_id",
        join( "', '", $post_types ),
        join( "', '", $taxonomies )
    );

    $results = $wpdb->get_results( $query );

    return $results;

}

次佳解決方案

所以只是發生了,我需要這樣的項目,我正在工作。我只是寫一個查詢來選擇自定義類型的所有帖子,然後我查看我們使用的分類法的實際條件是什麼。

然後我使用 get_terms()獲得了該分類法的所有條款,然後我只使用了兩個列表中的那些,將其包裝在一個函數中,並且完成了。

但是,我需要更多的只是 ID:我需要的名稱,所以我添加了一個新的參數 $fields,所以我可以告訴函數返回什麼。然後我認為 get_terms 接受很多參數,我的功能僅限於一個 post 類型使用的術語,所以我再添加一個 if 語句,然後你去:

功能:

/* get terms limited to post type
 @ $taxonomies - (string|array) (required) The taxonomies to retrieve terms from.
 @ $args  -  (string|array) all Possible Arguments of get_terms http://codex.wordpress.org/Function_Reference/get_terms
 @ $post_type - (string|array) of post types to limit the terms to
 @ $fields - (string) What to return (default all) accepts ID,name,all,get_terms.
 if you want to use get_terms arguments then $fields must be set to 'get_terms'
*/
function get_terms_by_post_type($taxonomies,$args,$post_type,$fields = 'all'){
    $args = array(
        'post_type' => (array)$post_type,
        'posts_per_page' => -1
    );
    $the_query = new WP_Query( $args );
    $terms = array();
    while ($the_query->have_posts()){
        $the_query->the_post();
        $curent_terms = wp_get_object_terms( $post->ID, $taxonomy);
        foreach ($curent_terms as $t){
          //avoid duplicates
            if (!in_array($t,$terms)){
                $terms[] = $c;
            }
        }
    }
    wp_reset_query();
    //return array of term objects
    if ($fields == "all")
        return $terms;
    //return array of term ID's
    if ($fields == "ID"){
        foreach ($terms as $t){
            $re[] = $t->term_id;
        }
        return $re;
    }
    //return array of term names
    if ($fields == "name"){
        foreach ($terms as $t){
            $re[] = $t->name;
        }
        return $re;
    }
    // get terms with get_terms arguments
    if ($fields == "get_terms"){
        $terms2 = get_terms( $taxonomies, $args );
        foreach ($terms as $t){
            if (in_array($t,$terms2)){
                $re[] = $t;
            }
        }
        return $re;
    }
}

用法:

如果您只需要一個術語 ID 的列表,那麼:

$terms = get_terms_by_post_type('tag','','snippet','ID');

如果您只需要一個名詞列表,那麼:

$terms = get_terms_by_post_type('tag','','snippet','name');

如果您只需要一個術語對象列表,那麼:

$terms = get_terms_by_post_type('tag','','snippet');

如果您需要使用 get_terms 的額外參數,如:orderby,order,hierarchical …

$args = array('orderby' => 'count', 'order' => 'DESC',  'hide_empty' => 1);
$terms = get_terms_by_post_type('tag',$args,'snippet','get_terms');

請享用!

更新:

將術語數量修正為特定的職位類型更改:

foreach ($current_terms as $t){
          //avoid duplicates
            if (!in_array($t,$terms)){
                $terms[] = $t;
            }
        }

至:

foreach ($current_terms as $t){
    //avoid duplicates
    if (!in_array($t,$terms)){
        $t->count = 1;
        $terms[] = $t;
    }else{
        $key = array_search($t, $terms);
        $terms[$key]->count = $terms[$key]->count + 1;
    }
}

第三種解決方案

我寫了一個函數,可以將 $args 數組中的 post_type 傳遞給 get_terms()函數:

HT 到 @braydon 寫 SQL 。

 /**
 * terms_clauses
 *
 * filter the terms clauses
 *
 * @param $clauses array
 * @param $taxonomy string
 * @param $args array
 * @return array
**/
function terms_clauses($clauses, $taxonomy, $args)
{
    global $wpdb;

    if ($args['post_type'])
    {
        $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id";
        $clauses['where'] .= " AND p.post_type='{$args['post_type']}'";
    }
    return $clauses;
}
add_filter('terms_clauses', 'terms_clauses', 10, 3);

第四種方案

偉大的問題和堅實的答案。

我非常喜歡 @jessica 使用 terms_clauses 濾鏡的方法,因為它以非常合理的方式擴展了 get_terms 功能。

我的代碼是她的想法的延續,一些來自 @braydon 的 sql 可以減少重複。它還允許一個 post_types 陣列:

/**
 * my_terms_clauses
 *
 * filter the terms clauses
 *
 * @param $clauses array
 * @param $taxonomy string
 * @param $args array
 * @return array
 **/
function my_terms_clauses($clauses, $taxonomy, $args)
{
  global $wpdb;

  if ($args['post_types'])
  {
    $post_types = $args['post_types'];

    // allow for arrays
    if ( is_array($args['post_types']) ) {
      $post_types = implode("','", $args['post_types']);
    }
    $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id";
    $clauses['where'] .= " AND p.post_type IN ('". esc_sql( $post_types ). "') GROUP BY t.term_id";
  }
  return $clauses;
}
add_filter('terms_clauses', 'my_terms_clauses', 99999, 3);

因為 get_terms 沒有 GROUPY BY 的子句,所以我不得不將其添加到 WHERE 子句的末尾。請注意,我有過濾器優先級設置為 very-high,希望它總是最後一次。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。