利用 WP_Term_Query
优化分类和标签的查询性能
大家好,今天我们来深入探讨如何利用 WordPress 的 WP_Term_Query
类来优化分类和标签的查询性能。在大型 WordPress 站点中,分类和标签的使用非常普遍,但如果不注意查询方式,很容易造成性能瓶颈。WP_Term_Query
提供了一种更灵活、更高效的方式来检索 term 数据,通过合理地使用其参数和缓存机制,可以显著提升网站的响应速度。
1. WP_Term_Query
简介
WP_Term_Query
是 WordPress 4.6 版本引入的一个类,用于构造和执行分类(categories)和标签(tags)的查询。它允许我们通过一组参数来精确控制查询结果,例如按名称、ID、slug、term group 等进行过滤,并支持分页、排序等功能。与直接使用 get_terms()
函数相比,WP_Term_Query
提供了更强大的查询构建能力和更好的性能优化潜力。
2. 基本用法
首先,让我们来看一个 WP_Term_Query
的基本使用示例:
<?php
$args = array(
'taxonomy' => 'category', // 查询的分类法,可以是 'category'、'post_tag' 或自定义分类法
'hide_empty' => true, // 是否隐藏空分类,默认为 true
);
$term_query = new WP_Term_Query( $args );
if ( ! empty( $term_query->terms ) ) {
foreach ( $term_query->terms as $term ) {
echo '<p>' . esc_html( $term->name ) . '</p>';
}
} else {
echo '<p>No categories found.</p>';
}
?>
这段代码创建了一个 WP_Term_Query
实例,指定了要查询的分类法为 ‘category’,并设置 hide_empty
为 true,表示只显示包含文章的分类。然后,它遍历查询结果并输出分类名称。
3. 核心参数详解
WP_Term_Query
接受一个关联数组作为参数,下面是一些最常用的参数及其说明:
参数名 | 数据类型 | 描述 | 默认值 |
---|---|---|---|
taxonomy |
string/array | 指定要查询的分类法。可以是单个分类法名称(如 ‘category’),也可以是一个包含多个分类法名称的数组。 | ” |
object_ids |
int/array | 只返回与指定文章 ID 关联的 terms。可以是一个单独的 ID 或一个包含多个 ID 的数组。 | null |
search |
string | 搜索词。根据 term 名称进行模糊匹配。 | ” |
slug |
string/array | 根据 term slug 进行过滤。可以是一个单独的 slug 或一个包含多个 slug 的数组。 | ” |
name |
string/array | 根据 term 名称进行过滤。可以是一个单独的名称或一个包含多个名称的数组。 | ” |
term_id |
int/array | 根据 term ID 进行过滤。可以是一个单独的 ID 或一个包含多个 ID 的数组。 | ” |
term_taxonomy_id |
int/array | 根据 term taxonomy ID 进行过滤。可以是一个单独的 ID 或一个包含多个 ID 的数组。 | ” |
hide_empty |
bool | 是否隐藏空分类/标签。如果设置为 true,则只返回包含文章的 term。 | true |
number |
int | 要返回的 term 的数量。如果设置为 0,则返回所有符合条件的 term。 | 0 |
offset |
int | 从结果集的哪个位置开始返回。用于分页。 | null |
orderby |
string | 排序字段。可以是 ‘name’、’slug’、’term_id’、’count’ 或 ‘term_group’。 | ‘name’ |
order |
string | 排序方式。可以是 ‘ASC’(升序)或 ‘DESC’(降序)。 | ‘ASC’ |
fields |
string | 返回的数据类型。可以是 ‘all’(返回所有 term 对象)、’ids’(只返回 term ID 的数组)、’names’(只返回 term 名称的数组)或 ‘count’(只返回 term 的数量)。 | ‘all’ |
parent |
int | 只返回指定 term ID 的子 term。 | ” |
child_of |
int | 返回指定 term ID 的所有后代 term。 | ” |
childless |
bool | 如果设置为 true,则只返回没有子 term 的 term。 | false |
hierarchical |
bool | 是否返回分层结构。如果设置为 true,则返回一个分层结构的 term 数组。仅当 taxonomy 是分层结构时有效,例如 category。 | true |
pad_counts |
bool | 是否填充 term 的文章数量。如果设置为 true,则会递归地计算所有后代 term 的文章数量。 | false |
cache_domain |
string | 用于缓存的域名。默认为 ‘core’。 | ‘core’ |
update_term_meta_cache |
bool | 是否更新 term meta 缓存。如果设置为 true,则会在查询时更新 term meta 缓存。 | true |
meta_query |
array | 用于根据 term meta 进行过滤的查询参数。与 WP_Query 的 meta_query 参数类似。 |
” |
meta_key |
string | 要查询的 term meta 键名。 | ” |
meta_value |
string | 要查询的 term meta 值。 | ” |
meta_compare |
string | term meta 值的比较方式。可以是 ‘=’, ‘!=’, ‘>’, ‘>=’, ‘<‘, ‘<=’, ‘LIKE’, ‘NOT LIKE’, ‘IN’, ‘NOT IN’, ‘BETWEEN’, ‘NOT BETWEEN’, ‘EXISTS’, ‘NOT EXISTS’。 | ‘=’ |
suppress_filter |
bool | 是否阻止应用任何 term 查询过滤器。设置为 true 时,将禁用所有已注册的 get_terms 过滤器。谨慎使用,因为它可能会影响插件和主题的功能。 |
false |
4. 优化技巧
4.1 精确查询
避免使用宽泛的查询条件,尽量使用精确的查询参数。例如,如果只需要查询特定 ID 的分类,就不要使用 search
参数进行模糊匹配。
// 不推荐:模糊匹配
$args = array(
'taxonomy' => 'category',
'search' => '新闻', // 如果有很多分类名称包含“新闻”,则效率较低
);
// 推荐:精确匹配
$args = array(
'taxonomy' => 'category',
'name' => '新闻', // 只查询名称为“新闻”的分类
);
// 更加推荐:如果知道 ID,直接使用 ID 查询
$args = array(
'taxonomy' => 'category',
'term_id' => 123, // 查询 ID 为 123 的分类
);
4.2 使用 fields
参数
fields
参数可以控制返回的数据类型。如果只需要 term ID 或名称,就不要返回完整的 term 对象。
// 只获取 term ID
$args = array(
'taxonomy' => 'category',
'fields' => 'ids', // 只返回 term ID 的数组
);
$term_query = new WP_Term_Query( $args );
if ( ! empty( $term_query->terms ) ) {
foreach ( $term_query->terms as $term_id ) {
echo '<p>Term ID: ' . esc_html( $term_id ) . '</p>';
}
}
4.3 缓存
WordPress 提供了 term 缓存机制,可以显著提升查询性能。WP_Term_Query
默认会使用缓存,但可以通过 cache_domain
参数来控制缓存的域名。
此外,还可以使用 WordPress 的 transient API 来手动缓存查询结果:
<?php
$cache_key = 'my_custom_category_query';
$cached_terms = get_transient( $cache_key );
if ( false === $cached_terms ) {
// 缓存不存在,执行查询
$args = array(
'taxonomy' => 'category',
'number' => 10,
);
$term_query = new WP_Term_Query( $args );
$cached_terms = $term_query->terms;
// 缓存查询结果,有效期为 1 小时
set_transient( $cache_key, $cached_terms, 3600 );
}
if ( ! empty( $cached_terms ) ) {
foreach ( $cached_terms as $term ) {
echo '<p>' . esc_html( $term->name ) . '</p>';
}
}
?>
当分类或标签数据发生变化时,需要手动清除缓存:
// 清除缓存
delete_transient( 'my_custom_category_query' );
4.4 使用 object_ids
参数
如果需要查询与特定文章关联的分类或标签,可以使用 object_ids
参数。这比先获取所有分类/标签,然后再筛选与文章关联的 term 效率更高。
// 查询与文章 ID 为 123 关联的分类
$args = array(
'taxonomy' => 'category',
'object_ids' => 123,
);
$term_query = new WP_Term_Query( $args );
if ( ! empty( $term_query->terms ) ) {
foreach ( $term_query->terms as $term ) {
echo '<p>' . esc_html( $term->name ) . '</p>';
}
}
4.5 避免 N+1 查询
在循环中查询 term meta 时,容易出现 N+1 查询问题。可以使用 update_term_meta_cache
参数来批量加载 term meta,避免重复查询。
// 避免 N+1 查询
$args = array(
'taxonomy' => 'category',
'update_term_meta_cache' => true, // 批量加载 term meta
);
$term_query = new WP_Term_Query( $args );
if ( ! empty( $term_query->terms ) ) {
foreach ( $term_query->terms as $term ) {
$my_meta = get_term_meta( $term->term_id, 'my_meta_key', true );
echo '<p>' . esc_html( $term->name ) . ' - ' . esc_html( $my_meta ) . '</p>';
}
}
4.6 使用 meta_query
参数
当需要根据 term meta 进行过滤时,使用 meta_query
参数可以有效地减少查询结果集。
// 根据 term meta 进行过滤
$args = array(
'taxonomy' => 'category',
'meta_query' => array(
array(
'key' => 'my_meta_key',
'value' => 'my_meta_value',
'compare' => '=',
),
),
);
$term_query = new WP_Term_Query( $args );
if ( ! empty( $term_query->terms ) ) {
foreach ( $term_query->terms as $term ) {
echo '<p>' . esc_html( $term->name ) . '</p>';
}
}
4.7 合理使用 hide_empty
hide_empty
参数用于控制是否显示空 term。在某些场景下,显示空 term 可能没有意义,因此可以将其设置为 true
以减少查询结果集。但是,如果需要显示空 term,则应将其设置为 false
。
4.8 注意排序方式
orderby
参数用于指定排序字段,order
参数用于指定排序方式。合理的排序方式可以提高查询效率。例如,如果需要按照文章数量排序,可以将 orderby
设置为 count
。
4.9 索引优化
确保数据库中与 term 相关的字段(如 term_id, taxonomy, slug)都建立了索引。这可以显著提高查询速度,特别是对于大型站点。 可以使用phpMyAdmin 或者类似的数据库管理工具,手动为以下字段添加索引:
wp_terms
表的term_id
字段(通常主键已经有索引)wp_term_taxonomy
表的term_id
,taxonomy
和term_taxonomy_id
字段wp_term_relationships
表的term_taxonomy_id
和object_id
字段
注意: 修改数据库结构前,务必备份数据库,以防意外发生。
5. 性能测试
在进行任何优化之前,务必进行性能测试,以确定哪些查询是性能瓶颈。可以使用 WordPress 的 Query Monitor 插件来分析查询性能。
优化后,再次进行性能测试,以验证优化效果。
6. 总结
WP_Term_Query
是一个强大的工具,可以帮助我们更高效地查询分类和标签。通过精确查询、使用 fields
参数、缓存、使用 object_ids
参数、避免 N+1 查询、使用 meta_query
参数、合理使用 hide_empty
,以及索引优化等技巧,我们可以显著提升 WordPress 站点的性能。记住,性能优化是一个持续的过程,需要不断地测试和改进。
7. 优化 Term 查询的核心
理解 WP_Term_Query
的参数,并结合实际需求进行精确查询是优化 Term 查询的关键。同时,利用缓存机制和避免常见的性能陷阱,可以进一步提升查询效率。