各位观众老爷们,大家好! 今天咱们来聊聊 WordPress 里一对有点暧昧,又有点说不清道不明的关系:get_terms()
函数和 WP_Term_Query
类。 它们都负责从数据库里捞分类法(Taxonomy)的词条(Terms)出来,但捞的方法,捞的东西,还有背后的逻辑,可差了十万八千里。 别担心,咱们今天就用最通俗易懂的方式,把它们扒个底朝天,让大家明明白白,以后用起来才能得心应手。
第一回合:初识两位主角
-
get_terms()
函数:WordPress 的老牌劲旅get_terms()
函数是 WordPress 的元老级函数,它在 WordPress 早期就存在了。 它的主要作用就是根据给定的参数,从数据库里获取指定的分类法(比如分类、标签)的词条列表。简单来说,你可以把它想象成一个经验丰富的老厨师,你告诉他你要什么菜(分类法),要什么口味(参数),他就能从厨房(数据库)里给你端出一盘你想要的菜(词条列表)。
$terms = get_terms( array( 'taxonomy' => 'category', // 获取分类 'hide_empty' => true, // 隐藏空分类 'orderby' => 'name', // 按名称排序 'order' => 'ASC' // 升序 ) ); if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){ echo '<ul>'; foreach ( $terms as $term ) { echo '<li><a href="' . esc_url( get_term_link( $term ) ) . '">' . $term->name . '</a></li>'; } echo '</ul>'; }
这段代码就是用
get_terms()
函数获取所有非空的分类,并按照名称升序排列,然后把它们以列表的形式展示出来。 -
WP_Term_Query
类:WordPress 的后起之秀WP_Term_Query
类是 WordPress 4.6 版本引入的,它是一个更加灵活和面向对象的方式来查询分类法词条。你可以把它想象成一个更加现代化的厨房,你不仅可以告诉厨师你要什么菜,要什么口味,还可以告诉他你要用什么锅,要用什么火候,甚至可以自己动手参与烹饪的过程。
$args = array( 'taxonomy' => 'post_tag', // 获取标签 'hide_empty' => false, // 显示空标签 'orderby' => 'count', // 按文章数量排序 'order' => 'DESC', // 降序 'number' => 5 // 只获取前5个 ); $term_query = new WP_Term_Query( $args ); if ( ! empty( $term_query->terms ) ) { echo '<ul>'; foreach ( $term_query->terms as $term ) { echo '<li><a href="' . esc_url( get_term_link( $term ) ) . '">' . $term->name . '</a></li>'; } echo '</ul>'; }
这段代码就是用
WP_Term_Query
类获取文章数量最多的前 5 个标签,并按照文章数量降序排列,然后把它们以列表的形式展示出来。
第二回合:深入对比,揭秘差异
特性 | get_terms() |
WP_Term_Query |
---|---|---|
返回值 | 词条对象数组或 WP_Error 对象 | 一个 WP_Term_Query 对象,词条在 terms 属性中 |
参数传递方式 | 数组 | 数组 |
灵活性 | 相对较低,参数有限 | 较高,支持更复杂的查询参数和钩子 |
性能 | 在简单查询中可能更快 | 在复杂查询中可能更有效率,因为支持缓存 |
钩子 | 支持的钩子较少 | 支持更多的钩子,方便自定义查询行为 |
对象导向 | 非对象导向 | 对象导向 |
缓存 | 有缓存机制,但不如 WP_Term_Query 精细 |
有更精细的缓存机制,可以更好地利用 WordPress 的对象缓存 |
适用场景 | 简单查询,需要快速获取词条列表 | 复杂查询,需要更多的控制和自定义 |
接下来,咱们就针对表格里的几个关键点,进行更深入的探讨:
-
返回值:不仅是数据,更是姿势
get_terms()
函数直接返回一个词条对象数组,或者在出错的时候返回一个WP_Error
对象。 拿到数据之后,你就可以直接用了。$terms = get_terms( 'category' ); if ( ! is_wp_error( $terms ) ) { foreach ( $terms as $term ) { // 直接访问 $term 的属性,比如 $term->name, $term->slug } }
而
WP_Term_Query
类返回的是一个WP_Term_Query
对象。 你需要访问这个对象的terms
属性才能拿到词条数组。$term_query = new WP_Term_Query( array( 'taxonomy' => 'category' ) ); if ( ! empty( $term_query->terms ) ) { foreach ( $term_query->terms as $term ) { // 直接访问 $term 的属性,比如 $term->name, $term->slug } }
虽然都是拿到数据,但
WP_Term_Query
这种方式更加面向对象,也更方便进行一些高级操作,比如分页。 -
灵活性:参数的多少,决定了你的自由度
get_terms()
函数支持的参数相对较少,虽然也能满足大部分的需求,但在一些复杂的查询场景下,就显得有些力不从心了。比如,你想根据某个自定义字段的值来筛选词条,
get_terms()
就无能为力了。而
WP_Term_Query
类支持更多的参数,并且可以通过钩子来扩展查询条件,因此更加灵活。比如,你可以用
meta_query
参数来根据自定义字段的值来筛选词条。$args = array( 'taxonomy' => 'category', 'meta_query' => array( array( 'key' => 'my_custom_field', 'value' => 'my_custom_value', 'compare' => '=' ) ) ); $term_query = new WP_Term_Query( $args );
这段代码就是用
WP_Term_Query
类获取所有my_custom_field
自定义字段的值等于my_custom_value
的分类。 -
性能:速度与激情的抉择
在简单的查询场景下,
get_terms()
函数可能更快,因为它直接从数据库里获取数据,没有额外的对象创建和处理的开销。但在复杂的查询场景下,
WP_Term_Query
类可能更有效率,因为它支持更精细的缓存机制,可以更好地利用 WordPress 的对象缓存。WP_Term_Query
允许你控制是否缓存结果,以及缓存的键值,这在处理大量数据或者频繁查询时非常有用。此外,
WP_Term_Query
还可以通过 SQL 优化来提高查询效率,比如使用JOIN
语句来关联多个表。 -
钩子:给你更多掌控权
get_terms()
函数支持的钩子较少,主要是一些用于修改查询参数和结果的钩子。而
WP_Term_Query
类支持更多的钩子,比如pre_get_terms
,terms_clauses
,get_terms
等,这些钩子可以让你在查询的不同阶段,对查询进行自定义修改。比如,你可以用
terms_clauses
钩子来修改 SQL 查询语句,实现一些非常规的查询需求。add_filter( 'terms_clauses', 'my_custom_terms_clauses', 10, 3 ); function my_custom_terms_clauses( $clauses, $taxonomies, $args ) { // 在这里修改 SQL 查询语句 $clauses['where'] .= " AND t.name LIKE '%my_keyword%'"; return $clauses; } $term_query = new WP_Term_Query( array( 'taxonomy' => 'category' ) );
这段代码就是用
terms_clauses
钩子来修改 SQL 查询语句,只获取名称包含my_keyword
的分类。 -
缓存:记忆力决定效率
get_terms()
和WP_Term_Query
都有缓存机制,但WP_Term_Query
的缓存机制更加精细。get_terms()
的缓存主要依赖于 WordPress 的对象缓存,它会把查询结果缓存到对象缓存中,下次查询的时候直接从缓存中获取数据。WP_Term_Query
除了利用对象缓存之外,还可以通过cache_domain
和cache_key
参数来控制缓存的行为。cache_domain
参数用于指定缓存的域名,cache_key
参数用于指定缓存的键值。通过这两个参数,你可以更精确地控制缓存的生命周期和刷新策略。
第三回合:源码剖析,深入骨髓
光说不练假把式,接下来咱们就来扒一扒 get_terms()
函数和 WP_Term_Query
类的源码,看看它们内部是怎么运作的。
-
get_terms()
函数源码分析get_terms()
函数位于wp-includes/taxonomy.php
文件中。它的主要流程如下:
- 参数处理: 对传入的参数进行处理,包括参数的类型转换、默认值设置等。
- 缓存检查: 检查缓存中是否存在查询结果,如果存在则直接返回缓存结果。
- 构建查询参数: 根据传入的参数,构建查询参数数组。
- 调用
_get_terms()
函数: 调用_get_terms()
函数执行实际的数据库查询。 - 结果处理: 对查询结果进行处理,包括对象转换、排序等。
- 缓存设置: 将查询结果缓存到对象缓存中。
- 返回结果: 返回查询结果。
其中,
_get_terms()
函数是get_terms()
函数的核心,它负责执行实际的数据库查询。_get_terms()
函数的主要流程如下:- 构建 SQL 查询语句: 根据查询参数,构建 SQL 查询语句。
- 执行 SQL 查询: 执行 SQL 查询,获取查询结果。
- 结果处理: 对查询结果进行处理,包括对象转换等。
- 返回结果: 返回查询结果。
从源码可以看出,
get_terms()
函数的实现比较简单,主要就是构建 SQL 查询语句,然后执行查询,最后返回结果。 -
WP_Term_Query
类源码分析WP_Term_Query
类位于wp-includes/class-wp-term-query.php
文件中。它的主要流程如下:
- 参数处理: 对传入的参数进行处理,包括参数的类型转换、默认值设置等。
- 构建查询参数: 根据传入的参数,构建查询参数数组。
- 应用钩子: 应用
pre_get_terms
钩子,允许在查询之前修改查询参数。 - 构建 SQL 查询语句: 根据查询参数,构建 SQL 查询语句。
- 应用钩子: 应用
terms_clauses
钩子,允许修改 SQL 查询语句。 - 执行 SQL 查询: 执行 SQL 查询,获取查询结果。
- 结果处理: 对查询结果进行处理,包括对象转换等。
- 缓存设置: 将查询结果缓存到对象缓存中。
- 应用钩子: 应用
get_terms
钩子,允许在查询之后修改查询结果。 - 返回结果: 返回查询结果。
从源码可以看出,
WP_Term_Query
类的实现更加复杂,它使用了更多的钩子,允许在查询的不同阶段对查询进行自定义修改。此外,
WP_Term_Query
类还提供了更多的参数,可以实现更复杂的查询需求。
第四回合:实战演练,案例分析
说了这么多理论,不如来点实际的。 咱们来看几个实际的案例,看看在不同的场景下,应该选择 get_terms()
函数还是 WP_Term_Query
类。
-
案例 1:获取所有分类
如果你只需要获取所有分类,并且不需要进行复杂的筛选和排序,那么
get_terms()
函数就足够了。$categories = get_terms( 'category' ); if ( ! is_wp_error( $categories ) ) { // 处理分类数据 }
-
案例 2:获取指定分类下的所有子分类
如果你需要获取指定分类下的所有子分类,并且需要按照名称排序,那么
get_terms()
函数也可以胜任。$args = array( 'taxonomy' => 'category', 'parent' => $parent_id, 'orderby' => 'name', 'order' => 'ASC' ); $categories = get_terms( $args ); if ( ! is_wp_error( $categories ) ) { // 处理分类数据 }
-
案例 3:获取文章数量最多的前 5 个标签
如果你需要获取文章数量最多的前 5 个标签,并且需要按照文章数量降序排列,那么
WP_Term_Query
类就更适合。$args = array( 'taxonomy' => 'post_tag', 'orderby' => 'count', 'order' => 'DESC', 'number' => 5 ); $term_query = new WP_Term_Query( $args ); if ( ! empty( $term_query->terms ) ) { // 处理标签数据 }
-
案例 4:根据自定义字段的值筛选分类
如果你需要根据自定义字段的值来筛选分类,那么只能使用
WP_Term_Query
类。$args = array( 'taxonomy' => 'category', 'meta_query' => array( array( 'key' => 'my_custom_field', 'value' => 'my_custom_value', 'compare' => '=' ) ) ); $term_query = new WP_Term_Query( $args ); if ( ! empty( $term_query->terms ) ) { // 处理分类数据 }
第五回合:总结陈词,一锤定音
总而言之,get_terms()
函数和 WP_Term_Query
类都是 WordPress 中用于查询分类法词条的重要工具。
get_terms()
函数简单易用,适合简单的查询场景。
WP_Term_Query
类功能强大,灵活可扩展,适合复杂的查询场景。
在实际开发中,应该根据具体的需求,选择合适的工具。
希望今天的讲解能够帮助大家更好地理解 get_terms()
函数和 WP_Term_Query
类的关系和差异,并在实际开发中灵活运用它们。 谢谢大家!