问题描述
我有 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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。