如果我使用:
<?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。为什么?
#1 楼
恐怕这在本地是不可能的(还可以吗?)。参见以下内容: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
的附加参数,该参数采用一连串的帖子类型。但是我不能保证一切都按预期进行(我想填充计数)。使用默认的
$args
似乎确实可以使用。 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);
}
原始变通方法
从上面的trac票证启发而来,(经测试,对我有用)
$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'));
评论
它可以工作,但是我的$ args应该怎么办?我的意思是... parent = 0&orderby = name&hide_empty = 0
–user1443216
2012年7月4日在19:11
否-这必须是一个数组:$ args = array('parent'=> 0,'orderby'=>'name','hide_empty'=> 0);.我将对其进行编辑以允许查询字符串...
–斯蒂芬·哈里斯(Stephen Harris)
2012年7月4日19:44
我可以在以下示例中将$ args放在哪里:$ terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));?
–user1443216
2012年7月4日19:59
您不能在那一个中,只能在新的解决方案中:wpse57444_get_terms()
–斯蒂芬·哈里斯(Stephen Harris)
2012年7月4日在20:21
@ user1443216 $ args是第二个参数。在那里,您只需将wpse57444_get_terms('flag',array('country','city'));
– kaiser
2012年7月4日在20:21
#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' ) ); ?>
评论
根据此跟踪单,这似乎是推荐的方法:core.trac.wordpress.org/ticket/18106#comment:7。请注意,这可能非常慢,因此如果您的站点上有很多帖子,则可能需要实现一些缓存。
–法律
20/11/11在14:25
#3 楼
上面@ stephen-harris的答案仅对我有用。如果我尝试在页面上使用两次,则无法正常工作。另外,像这样埋入mysql查询的想法让我担心-我认为使用核心方法来实现解决方案是更好的做法,以避免与将来的WP更新产生冲突。这是我的解决方案,基于他参考的Trac票上的一些注释#7function 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线程,虽然有人提到它可能无法很好地扩展,但是我的工作规模很小,并且速度没有问题。
评论
这个解决方案看起来更像“本机”-无论如何->您应该在循环的“ endwhile”之后立即调用“ wp_reset_postdata()”:wordpress.stackexchange.com/questions/144343 / ...
–托马斯·费林格
17年11月22日在10:04
#4 楼
[edit]这是对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 #5 楼
我也尝试使用@Stephen Harris的答案,但是我需要的查询很难作为一个查询和过滤器来编写。此外,我还需要在函数中多次使用该函数。在同一页面上,我解决了在包装函数之外声明
wpse_filter_terms_by_cpt
函数的问题。无论如何,由于他说的相同原因,@ Mark Pruce的答案更合适,尽管它需要您做出再进行一次查询(以及相关的循环)以为
wp_get_object_terms
函数准备args。
评论
你能说清楚一点吗?