按分类和POST_TYPE获取术语

时间:2011-04-09 作者:Gavin Hewitt

我有两个自定义帖子类型“bookmarks”和“snippets”,还有一个共享的分类法“tag”。我可以使用get\\u terms()生成分类法中所有术语的列表,但我不知道如何将列表限制为post类型。我基本上是在寻找这样的东西:

get_terms(array(\'taxonomy\' => \'tag\', \'post_type\' => \'snippet\'));
有没有办法做到这一点?非常感谢您的想法!!

哦,我在WP 3.1.1上

7 个回复
最合适的回答,由SO网友:Braydon 整理而成

下面是使用一个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;

}

SO网友:Bainternet

所以碰巧我正在做的一个项目需要这样的东西。我只是编写了一个查询来选择一个自定义类型的所有帖子,然后检查他们使用的分类法的实际术语是什么。

然后我用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\\u术语的额外参数,如: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;
    }
}

SO网友:daggerhart

很好的问题和可靠的答案。

我非常喜欢@jessica使用terms\\u子句过滤器的方法,因为它以非常合理的方式扩展了get\\u terms函数。

我的代码是她的想法的延续,使用@braydon的一些sql来减少重复。它还允许post\\u类型的数组:

/**
 * 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 = implode("\',\'", array_map(\'esc_sql\', (array) $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 (\'". $post_types. "\') GROUP BY t.term_id";
  }
  return $clauses;
}
add_filter(\'terms_clauses\', \'my_terms_clauses\', 99999, 3);
因为get\\u terms没有GROUPY BY的子句,所以我不得不将其添加到WHERE子句的末尾。请注意,我将过滤器优先级设置得非常高,希望它总是最后一个。

SO网友:jessica

我编写了一个函数,允许您通过post_type$args 阵列到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);

SO网友:tzeldin88

我无法使get\\u terms参数与上面Gavin版本的代码一起使用,但最终通过更改

$terms2 = get_terms( $taxonomy );

$terms2 = get_terms( $taxonomy, $args );
因为它是在贝恩特网的原始功能中。

SO网友:Gavin Hewitt

@班纳特:谢谢!我不得不稍微修改一下函数,因为它不起作用(有些输入错误)。现在唯一的问题是术语计数已关闭。计数没有考虑post类型,因此我认为您不能在此使用get\\u terms()。

function get_terms_by_post_type($post_type,$taxonomy,$fields=\'all\',$args){
    $q_args = array(
        \'post_type\' => (array)$post_type,
        \'posts_per_page\' => -1
    );
    $the_query = new WP_Query( $q_args );

    $terms = array();

    while ($the_query->have_posts()) { $the_query->the_post();

        global $post;

        $current_terms = get_the_terms( $post->ID, $taxonomy);

        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;
            }
        }
    }
    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( $taxonomy, $args );

        foreach ($terms as $t){
            if (in_array($t,$terms2)){
                $re[] = $t;
            }
        }
        return $re;
    }
}
编辑:添加了修复。但不知怎么的,这对我还是不起作用。计数仍显示不正确的值。

SO网友:Kaotiko

Avoid Duplicates:

//avoid duplicates
    $mivalor=$t->term_id;
    $arr=array_filter($terms, function ($item) use ($mivalor) {return isset($item->term_id) && $item->term_id == $mivalor;});

    if (empty($arr)){
    $t->count=1;
            $terms[] = $t;
        }else{
            $key = array_search($t, $terms);
            $terms[$key]->count = $terms[$key]->count + 1;
        }
结束

相关推荐

从Terms()函数中去掉标记

正在尝试打印自定义帖子类型的分类法,但没有链接。尝试过这个,但似乎不起作用,有什么建议吗?$text = the_terms($post->ID,\'type\',\'\',\'\',\'\'); echo strip_tags($text); 任何帮助都将不胜感激。。。我要开始揍婴儿了。