通过自定义帖子类型获取get_terms


19

我有两个自定义帖子类型“国家”和“城市”,以及一个共享的分类法“标志”。

如果我使用:

<?php $flags = get_terms('flag', 'orderby=name&hide_empty=0');

我得到了分类法中所有术语的列表,但是我想将列表限制为“国家”这一职位类型。

我该怎么做?


使用新的解决方案

<?php 
$flags = wpse57444_get_terms('flags',array('parent' => 0,'hide_empty' => 1,'post_types' =>array('country')));
foreach ($flags as $flag) {
    $childTerms = wpse57444_get_terms('flags',array('parent' => $flag->term_id,'hide_empty' => 1,'post_types' =>array('country')));
    foreach ($childTerms as $childTerm) {
        echo $childTerm->name.'<br />';
    }
}
?>

我无法回显$ childTerm-> name。为什么?


你能说清楚一点吗?
TheDeadMedic 2012年

Answers:


16

恐怕这是不可能的(还好吗?)。看到这个轨迹:http : //core.trac.wordpress.org/ticket/18106

同样,在分类管理页面上,帖子计数反映所有帖子类型。(我很确定也有相应的追踪票http://core.trac.wordpress.org/ticket/14084

另请参阅此相关文章


新解决方案

在写完下面的内容后,我发布了一种更好的方法(从某种意义上讲,您可以做更多的事情)是使用get_terms()通话中提供的过滤器。您可以创建使用get_terms和(有条件地)添加过滤器以操纵SQL查询(以帖子类型限制)的包装器函数。

该函数采用与相同的参数get_terms($taxonomies, $args)$args采用附加参数,post_types该参数采用帖子类型的字符串。

但是我不能保证一切都“按预期”进行(我正在考虑增加计数)。仅使用默认的$argsfor 似乎可以工作get_terms

function wpse57444_get_terms( $taxonomies, $args=array() ){
    //Parse $args in case its a query string.
    $args = wp_parse_args($args);

    if( !empty($args['post_types']) ){
        $args['post_types'] = (array) $args['post_types'];
        add_filter( 'terms_clauses','wpse_filter_terms_by_cpt',10,3);

        function wpse_filter_terms_by_cpt( $pieces, $tax, $args){
            global $wpdb;

            // Don't use db count
            $pieces['fields'] .=", COUNT(*) " ;

            //Join extra tables to restrict by post type.
            $pieces['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 ";

            // Restrict by post type and Group by term_id for COUNTing.
            $post_types_str = implode(',',$args['post_types']);
            $pieces['where'].= $wpdb->prepare(" AND p.post_type IN(%s) GROUP BY t.term_id", $post_types_str);

            remove_filter( current_filter(), __FUNCTION__ );
            return $pieces;
        }
    } // endif post_types set

    return get_terms($taxonomies, $args);           
}

用法

$args =array(
    'hide_empty' => 0,
    'post_types' =>array('country','city'),
);

$terms = wpse57444_get_terms('flag',$args);

原始解决方法

灵感来自上面的票,(经过测试,对我有用)

function wpse57444_filter_terms_by_cpt($taxonomy, $post_types=array() ){
    global $wpdb;

    $post_types=(array) $post_types;
    $key = 'wpse_terms'.md5($taxonomy.serialize($post_types));
    $results = wp_cache_get($key);

    if ( false === $results ) {
       $where =" WHERE 1=1";
       if( !empty($post_types) ){
            $post_types_str = implode(',',$post_types);
            $where.= $wpdb->prepare(" AND p.post_type IN(%s)", $post_types_str);
       }

       $where .= $wpdb->prepare(" AND tt.taxonomy = %s",$taxonomy);

       $query = "
          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
          GROUP BY t.term_id";

       $results = $wpdb->get_results( $query );
       wp_cache_set( $key, $results );
    }        

    return $results;
}

用法

 $terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));

要么

 $terms = wpse57444_filter_terms_by_cpt('flag','country');

它可以工作,但是我的$ args应该怎么办?我的意思是... parent = 0&orderby = name&hide_empty = 0
user1443216

否-这必须是一个数组:$args = array('parent'=>0,'orderby'=>'name','hide_empty'=>0);。我将对其进行编辑以允许查询字符串...
Stephen Harris

在此示例中,我可以将$ args放在哪里$terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));
user1443216 2012年

您不能在那一个中​​,只能在新的解决方案中:wpse57444_get_terms()
Stephen Harris

@ user1443216 $args是第二个参数。您就wpse57444_get_terms( 'flag', array( 'country', 'city' ) );
kaiser

2

上面@ stephen-harris的答案仅对我有用。如果我尝试在页面上使用两次,则无法正常工作。另外,像这样埋入mysql查询的想法让我感到担忧-我认为使用核心方法来实现解决方案是更好的做法,以避免与将来的WP更新产生冲突。这是我的解决方案,基于他参考的Trac票上的一些评论#7

function get_terms_by_custom_post_type( $post_type, $taxonomy ){
  $args = array( 'post_type' => $post_type);
  $loop = new WP_Query( $args );
  $postids = array();
  // build an array of post IDs
  while ( $loop->have_posts() ) : $loop->the_post();
    array_push($postids, get_the_ID());
  endwhile;
  // get taxonomy values based on array of IDs
  $regions = wp_get_object_terms( $postids,  $taxonomy );
  return $regions;
}

用法:

$terms = get_terms_by_custom_post_type('country','flag');

这仅适用于一种帖子类型和一种分类法,因为这是我所需要的,但是修改它以接受多个值并不难。

在Trac线程上有人提到它可能无法很好地扩展,但是我的工作规模很小,并且速度没有问题。


该解决方案看起来更“本土”到眉-反正- >你应该叫“wp_reset_postdata()的”循环“ENDWHILE”之后:wordpress.stackexchange.com/questions/144343/...
托马斯Fellinger

2

两种自定义帖子类型“国家”和“城市”以及共享的分类法“标志”。您希望将列表限制为帖子类型“国家”。

这是一个更简单的解决方案:

$posts_in_post_type = get_posts( array(
    'fields' => 'ids',
    'post_type' => 'country',
    'posts_per_page' => -1,
) );
$terms = wp_get_object_terms( $posts_in_post_type, 'flag', array( 'ids' ) ); ?>

1

[编辑]这是对斯蒂芬·哈里斯(Stephen Harris)出色回答的评论。

如果与像这样的多个帖子类型一起使用,它不会返回任何术语$flags = wpse57444_get_terms('flags', array('post_types' => array('country','city')));。这是因为$ wpdb-> prepare将$ post_types_str字符串清理为p.post_type IN('country,city')应为的字符串p.post_type IN('country','city')。看到这张票:11102。使用本主题中的解决方案可以解决此问题:https : //stackoverflow.com/a/10634225


1

我也尝试使用@Stephen Harris的答案,但是我需要的查询作为单个查询和使用过滤器很难编写。

此外,我还需要在同一页面中多次使用该函数,并且解决了wpse_filter_terms_by_cpt在包装函数之外声明该函数的问题。

无论如何,出于他说的相同原因,我认为@Mark Pruce的答案更合适,尽管它需要您再进行一次查询(和相关的循环)来为wp_get_object_terms函数准备args 。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.