各位观众老爷们,晚上好!今天咱们来聊聊 WordPress 的 get_terms()
函数,这玩意儿用起来挺方便,但背地里其实调用了一个更强大的类——WP_Term_Query
。咱们一起扒一扒它的源码,看看它是怎么把数据库里的分类术语(categories, tags, etc.)给揪出来的。
get_terms()
:门面担当
首先,咱们得对 get_terms()
有个大致了解。这函数就像个友好的服务员,你告诉它想吃啥(参数),它就去厨房(数据库)给你端上来。
简单来说,get_terms()
的作用就是根据你提供的参数,从数据库中获取分类术语(Term)。这些参数可以包括:
taxonomy
:指定要查询的分类法(例如:’category’,’post_tag’)。hide_empty
:是否隐藏没有文章的术语。orderby
:按什么排序(例如:’name’,’count’)。order
:升序还是降序(’ASC’,’DESC’)。number
:返回多少个术语。offset
:从第几个术语开始返回。search
:搜索匹配的术语名称。slug
:通过slug查找术语。term_taxonomy_id
:通过term_taxonomy_id查找术语。
等等等等,一大堆。
<?php
// 举个栗子:获取所有 category 分类下的术语,按名称升序排列
$terms = get_terms( array(
'taxonomy' => 'category',
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false, //显示空的分类
) );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
echo '<ul>';
foreach ( $terms as $term ) {
echo '<li>' . esc_html( $term->name ) . '</li>';
}
echo '</ul>';
}
?>
这段代码的作用就是从 'category'
分类法中取出所有术语,按照名称升序排列,并显示出来。
WP_Term_Query
:幕后英雄
现在,重点来了。get_terms()
函数真正干活的,其实是 WP_Term_Query
类。 它就像厨房里的主厨,负责把服务员点的菜变成现实。
让我们一起潜入 wp-includes/class-wp-term-query.php
文件,看看这主厨是怎么工作的。
首先,找到 WP_Term_Query
类的定义。你会发现它继承了一个名为 WP_Query
的类,而 WP_Query
是 WordPress 中用于查询各种数据的核心类。 WP_Term_Query
特化了 WP_Query
,专门用于查询分类术语。
WP_Term_Query::__construct()
:初始化查询参数
WP_Term_Query
类的构造函数 __construct()
负责接收查询参数,并进行一些必要的预处理。
public function __construct( $query = '' ) {
if ( ! empty( $query ) ) {
$this->query( $query );
}
}
很简单,如果传入了查询参数 $query
,就调用 query()
方法来处理。
WP_Term_Query::query()
:参数解析与处理
query()
方法是整个查询流程的核心。它接收一个参数数组,然后将这些参数转换为 SQL 查询语句。
public function query( $query ) {
$this->query_vars = wp_parse_args( $query, $this->defaults );
return $this->get_terms();
}
这里做了两件事:
wp_parse_args()
:这个函数将传入的参数$query
与默认参数$this->defaults
合并。$this->defaults
定义了WP_Term_Query
的默认参数值。 这样可以确保所有必要的参数都有值,即使调用者没有显式指定。$this->get_terms()
:调用get_terms()
方法执行实际的查询操作。
WP_Term_Query::get_terms()
:执行查询
get_terms()
方法负责根据查询参数构建 SQL 查询语句,并从数据库中获取结果。
public function get_terms() {
global $wpdb;
//... 省略一些钩子和缓存相关的代码 ...
$fields = $this->parse_fields(); //解析查询字段
$clauses = $this->get_sql_clauses(); //构建 SQL 查询语句
$this->sql = "SELECT $fields FROM {$wpdb->terms} AS t {$clauses['join']} WHERE 1=1 {$clauses['where']} {$clauses['orderby']} {$clauses['limits']}";
//... 省略一些调试和缓存相关的代码 ...
$terms = $wpdb->get_results( $this->sql );
//... 省略一些结果处理和对象缓存相关的代码 ...
return $terms;
}
这段代码的关键步骤:
$this->parse_fields()
:确定要查询哪些字段。默认情况下,查询所有字段。$this->get_sql_clauses()
:构建 SQL 查询语句的各个部分,包括JOIN
,WHERE
,ORDER BY
和LIMIT
子句。$this->sql = ...
:将各个部分拼接成完整的 SQL 查询语句。$wpdb->get_results( $this->sql )
:执行 SQL 查询,并返回结果。
WP_Term_Query::parse_fields()
:确定查询字段
这个方法决定了 SQL 查询语句中 SELECT
后面跟着什么。
protected function parse_fields() {
if ( isset( $this->query_vars['fields'] ) ) {
$fields = $this->query_vars['fields'];
} else {
$fields = 'all';
}
if ( 'all' == $fields ) {
return 't.*, tt.*'; //查询terms表和term_taxonomy表的所有字段
} elseif ( 'ids' == $fields ) {
return 't.term_id'; //只查询term_id
} elseif ( 'names' == $fields ) {
return 't.name'; //只查询name
} elseif ( 'count' == $fields ) {
return 'COUNT(*)'; //查询数量
} else {
return 't.*, tt.*'; //默认查询所有字段
}
}
根据 $this->query_vars['fields']
的值,返回不同的字段列表。
WP_Term_Query::get_sql_clauses()
:构建 SQL 子句
这是整个查询过程中最复杂的部分。这个方法负责根据查询参数构建 SQL 查询语句的各个子句,例如 JOIN
,WHERE
,ORDER BY
和 LIMIT
。
protected function get_sql_clauses() {
global $wpdb;
$orderby = $this->parse_orderby();
$order = strtoupper( $this->query_vars['order'] );
if ( ! in_array( $order, array( 'ASC', 'DESC' ), true ) ) {
$order = 'ASC';
}
$number = absint( $this->query_vars['number'] );
$offset = absint( $this->query_vars['offset'] );
$limits = '';
if ( ! empty( $number ) ) {
if ( empty( $offset ) ) {
$limits = "LIMIT $number";
} else {
$limits = "LIMIT $offset, $number";
}
}
$where = '';
$join = '';
// taxonomy参数,用于筛选特定的分类法
if ( ! empty( $this->query_vars['taxonomy'] ) ) {
$taxonomies = wp_parse_slug_list( $this->query_vars['taxonomy'] );
if ( $taxonomies ) {
$taxonomies = esc_sql( $taxonomies );
$where .= " AND tt.taxonomy IN ('" . implode( "', '", $taxonomies ) . "')";
}
}
// hide_empty参数,用于隐藏没有文章的术语
if ( $this->query_vars['hide_empty'] && 'count' !== $this->query_vars['fields'] ) {
$where .= ' AND tt.count > 0';
}
// ...省略了处理其他参数的代码...
//orderby子句
$orderby_clause = '';
if ( ! empty( $orderby ) ) {
$orderby_clause = 'ORDER BY ' . implode( ', ', $orderby );
}
return compact( 'where', 'join', 'orderby_clause', 'limits' );
}
这个方法做了很多事情,包括:
- 处理
orderby
和order
参数,构建ORDER BY
子句。 - 处理
number
和offset
参数,构建LIMIT
子句。 - 处理
taxonomy
参数,构建WHERE
子句,用于筛选特定的分类法。 - 处理
hide_empty
参数,构建WHERE
子句,用于隐藏没有文章的术语。 - 处理其他各种参数,构建相应的 SQL 子句。
WP_Term_Query::parse_orderby()
:解析排序参数
这个方法用于解析 orderby
参数,并将其转换为 SQL 查询语句中的 ORDER BY
子句。
protected function parse_orderby() {
global $wpdb;
$orderby = $this->query_vars['orderby'];
if ( ! is_array( $orderby ) ) {
$orderby = preg_split( '/[,s]+/', $orderby );
}
$parsed_orderby = array();
foreach ( $orderby as $term ) {
$term = strtolower( $term );
switch ( $term ) {
case 'name':
$parsed_orderby[] = 't.name';
break;
case 'slug':
$parsed_orderby[] = 't.slug';
break;
case 'term_group':
$parsed_orderby[] = 't.term_group';
break;
case 'term_id':
$parsed_orderby[] = 't.term_id';
break;
case 'id':
$parsed_orderby[] = 't.term_id';
break;
case 'count':
$parsed_orderby[] = 'tt.count';
break;
case 'term_order':
$parsed_orderby[] = 'tt.term_order';
break;
default:
//... 省略一些处理自定义排序字段的代码 ...
break;
}
}
return $parsed_orderby;
}
这个方法根据 orderby
参数的值,将其转换为数据库字段名。例如,如果 orderby
的值为 'name'
,则将其转换为 't.name'
。
总结:get_terms()
和 WP_Term_Query
的关系
简单来说,get_terms()
是一个方便的函数,用于获取分类术语。它内部使用 WP_Term_Query
类来构建和执行 SQL 查询。 WP_Term_Query
类提供了更强大的查询功能,允许你使用各种参数来筛选和排序结果。
用表格来总结一下:
函数/类 | 作用 | 关系 |
---|---|---|
get_terms() |
提供一个方便的接口,用于获取分类术语。 | 调用 WP_Term_Query 类来执行查询。 |
WP_Term_Query |
构建 SQL 查询语句,从数据库中获取分类术语。 | 是 get_terms() 函数的幕后英雄。 |
实际应用场景
了解了 get_terms()
和 WP_Term_Query
的原理,我们就可以更灵活地使用它们。
例如,假设我们需要获取所有 'category'
分类下的术语,但是要排除 ID 为 1 和 2 的术语。我们可以这样做:
<?php
$args = array(
'taxonomy' => 'category',
'exclude' => array( 1, 2 ),
);
$terms = get_terms( $args );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
echo '<ul>';
foreach ( $terms as $term ) {
echo '<li>' . esc_html( $term->name ) . '</li>';
}
echo '</ul>';
}
?>
这里我们使用了 exclude
参数,用于排除指定的术语。
更高级的用法
如果你需要更精细的控制查询过程,你可以直接使用 WP_Term_Query
类。例如,你可以自定义 SQL 查询语句的 WHERE
子句。
<?php
$args = array(
'taxonomy' => 'category',
'name__like' => 'WordPress', // 查找名称包含 "WordPress" 的分类
);
$term_query = new WP_Term_Query( $args );
$terms = $term_query->get_terms();
if ( ! empty( $terms ) ) {
echo '<ul>';
foreach ( $terms as $term ) {
echo '<li>' . esc_html( $term->name ) . '</li>';
}
echo '</ul>';
}
?>
这个例子使用了 name__like
参数,用于查找名称包含 'WordPress'
的分类。
总结
好了,各位观众老爷们,今天我们一起深入研究了 WordPress 的 get_terms()
函数和 WP_Term_Query
类。希望通过今天的讲解,大家对 WordPress 的分类术语查询有了更深入的了解。下次再使用 get_terms()
的时候,心里就不会发虚了,因为你知道它背后的原理了。 记住,掌握了这些底层原理,才能更好地驾驭 WordPress 这匹野马!
下次再见!