WordPress get_term_by() 函数源码深度剖析:像侦探一样追踪你的分类术语
大家好!我是今天的主讲人,希望大家今天听完我的分享,都能像福尔摩斯一样,快速准确地在 WordPress 的分类术语世界里找到你想要的信息。
今天我们要深入探讨的是 WordPress 中一个非常实用的函数:get_term_by()。这个函数允许我们通过不同的属性(例如 slug、name、ID 等)来检索分类术语对象。我们将重点关注如何通过 slug 和 name 这两个属性高效地进行查询,并深入源码,看看 WordPress 内部是如何运作的。
1. get_term_by() 函数的基本用法
首先,让我们回顾一下 get_term_by() 函数的基本用法。它的函数签名如下:
get_term_by( string $field, mixed $value, string|array $taxonomy = 'category', string $output = OBJECT, string $filter = 'raw' )
$field: 我们要查询的字段。常见的选项有'id','slug','name','term_id'等。$value: 我们要查询的字段对应的值。$taxonomy: 分类术语的分类法(taxonomy)。默认为'category'。可以是一个字符串,也可以是一个字符串数组,代表多个分类法。$output: 返回值的类型。默认为OBJECT(WP_Term 对象)。也可以是ARRAY_A(关联数组) 或ARRAY_N(索引数组)。$filter: 对结果进行过滤。默认为'raw',不进行任何过滤。
例子:通过 slug 查找分类术语
$term = get_term_by( 'slug', 'my-awesome-category', 'category' );
if ( $term ) {
echo '分类术语名称: ' . $term->name . '<br>';
echo '分类术语 ID: ' . $term->term_id . '<br>';
echo '分类术语 slug: ' . $term->slug . '<br>';
} else {
echo '未找到分类术语。';
}
例子:通过 name 查找分类术语
$term = get_term_by( 'name', '我的超棒分类', 'category' );
if ( $term ) {
echo '分类术语名称: ' . $term->name . '<br>';
echo '分类术语 ID: ' . $term->term_id . '<br>';
echo '分类术语 slug: ' . $term->slug . '<br>';
} else {
echo '未找到分类术语。';
}
2. get_term_by() 源码剖析
现在,让我们深入到 WordPress 源码中,看看 get_term_by() 函数是如何实现的。这个函数位于 /wp-includes/taxonomy.php 文件中。
function get_term_by( $field, $value, $taxonomy = 'category', $output = OBJECT, $filter = 'raw' ) {
global $wpdb;
if ( ! taxonomy_exists( $taxonomy ) ) {
return false;
}
// 'id' is an alias for 'term_id'
if ( 'id' === $field ) {
$field = 'term_id';
}
if ( 'slug' === $field && empty( $value ) ) {
return false;
}
$taxonomies = (array) $taxonomy;
$term = false;
foreach ( $taxonomies as $taxonomy ) {
if ( ! taxonomy_exists( $taxonomy ) ) {
return false;
}
$term_id = false;
switch ( $field ) {
case 'term_id':
$term_id = absint( $value );
break;
case 'id': // Redundant, but kept for backwards compatibility.
$term_id = absint( $value );
break;
case 'slug':
$term_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms WHERE slug = %s", $value ) );
break;
case 'name':
$term_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms WHERE name = %s", $value ) );
break;
case 'term_taxonomy_id':
$term_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d AND taxonomy = %s", $value, $taxonomy ) );
break;
default:
/**
* Fires when an invalid field is requested.
*
* @since 4.4.0
*
* @param string $field The field used to search.
* @param mixed $value The field's value.
* @param string $taxonomy The taxonomy name.
*/
do_action( 'get_term_by_invalid_field', $field, $value, $taxonomy );
return false;
}
if ( $term_id ) {
$term = get_term( $term_id, $taxonomy, $output, $filter );
if ( $term && ! is_wp_error( $term ) ) {
break;
}
$term = false;
}
}
return $term;
}
让我们逐步分析:
-
参数验证:
- 首先,它检查指定的 taxonomy 是否存在。如果不存在,直接返回
false。 - 如果
$field是'id',则将其转换为'term_id',因为它们是等价的。 - 如果
$field是'slug'并且$value为空,则返回false,避免不必要的查询。
- 首先,它检查指定的 taxonomy 是否存在。如果不存在,直接返回
-
循环处理多个 Taxonomy:
$taxonomy参数可以是一个 taxonomy 字符串或一个 taxonomy 字符串数组。函数会循环处理这些 taxonomy,如果找到了匹配的 term,就会停止循环。
-
根据 Field 选择查询方式:
switch语句根据$field的值来选择不同的查询方式。- 如果
$field是'term_id'或'id',则直接将$value转换为整数,作为 term_id。 - 如果
$field是'slug'或'name',则使用$wpdb->get_var()方法执行 SQL 查询,从$wpdb->terms表中获取term_id。 - 如果
$field是'term_taxonomy_id',则使用$wpdb->get_var()方法执行 SQL 查询,从$wpdb->term_taxonomy表中获取term_id。 - 如果
$field是其他值,则触发get_term_by_invalid_fieldaction,并返回false。
-
获取 Term 对象:
- 如果找到了
term_id,则调用get_term()函数来获取完整的 term 对象。 - 如果
get_term()返回一个有效的 term 对象,并且不是 WP_Error 对象,则停止循环,返回 term 对象。 - 如果
get_term()返回false或 WP_Error 对象,则将$term设置为false,继续循环。
- 如果找到了
-
返回结果:
- 最后,函数返回
$term。如果找到了匹配的 term,则返回 term 对象;否则,返回false。
- 最后,函数返回
3. slug 和 name 查询的性能分析
当我们使用 slug 或 name 进行查询时,get_term_by() 函数会执行以下 SQL 查询:
使用 slug 查询:
SELECT term_id FROM wp_terms WHERE slug = '%s'
使用 name 查询:
SELECT term_id FROM wp_terms WHERE name = '%s'
这些查询语句都很简单,但是否高效取决于以下因素:
wp_terms表的大小: 如果wp_terms表包含大量的分类术语,查询速度可能会变慢。slug和name列的索引:wp_terms表的slug和name列默认都有索引。索引可以显著提高查询速度。
优化建议:
- 确保
slug和name列都有索引: WordPress 默认会创建这些索引,但如果你的数据库发生了意外情况(例如,手动修改了数据库结构),你需要检查一下这些索引是否存在。 - 避免使用过长的
slug或name: 过长的字符串会增加索引的大小,并可能降低查询速度。 - 如果可能,尽量使用
term_id进行查询: 通过term_id查询是最快的,因为它直接通过主键索引进行查找。 - 使用缓存: 如果你的网站需要频繁地查询相同的分类术语,可以考虑使用缓存来提高性能。WordPress 提供了 transient API,可以方便地缓存数据。
4. 代码示例:使用缓存优化 get_term_by()
/**
* 通过 slug 获取分类术语,使用缓存优化。
*
* @param string $slug 分类术语 slug.
* @param string $taxonomy 分类法.
*
* @return WP_Term|false 分类术语对象,如果未找到则返回 false.
*/
function get_term_by_slug_cached( $slug, $taxonomy = 'category' ) {
$cache_key = 'term_by_slug_' . $slug . '_' . $taxonomy;
$term = wp_cache_get( $cache_key, 'terms' );
if ( false === $term ) {
$term = get_term_by( 'slug', $slug, $taxonomy );
if ( $term ) {
wp_cache_set( $cache_key, $term, 'terms', 3600 ); // 缓存 1 小时
}
}
return $term;
}
// 使用示例
$term = get_term_by_slug_cached( 'my-awesome-category', 'category' );
if ( $term ) {
echo '分类术语名称: ' . $term->name . '<br>';
} else {
echo '未找到分类术语。';
}
这个例子展示了如何使用 WordPress 的 wp_cache_get() 和 wp_cache_set() 函数来缓存 get_term_by() 的结果。 这样可以避免每次都执行数据库查询,显著提高性能。
5. 总结与最佳实践
get_term_by() 函数是 WordPress 中一个非常重要的工具,可以帮助我们方便地检索分类术语信息。 通过深入了解它的源码和性能特点,我们可以更好地利用它,并避免一些常见的性能问题。
以下是一些最佳实践建议:
- 优先使用
term_id查询: 如果已知term_id,则直接使用get_term()函数进行查询,这是最快的。 - 使用缓存: 对于频繁查询的分类术语,使用缓存可以显著提高性能。
- 注意
slug和name的唯一性: 虽然 WordPress 允许同名的分类术语存在于不同的分类法中,但最好保持slug的唯一性,以避免混淆。 - 避免在循环中调用
get_term_by(): 如果在循环中需要查询多个分类术语,最好一次性获取所有需要的term_id,然后使用get_terms()函数批量获取 term 对象。 这样可以减少数据库查询次数,提高性能。 - 了解你的数据: 了解
wp_terms表的大小、索引情况等,可以帮助你更好地优化查询。
表格总结:
| 查询方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
term_id |
最快,直接使用主键索引 | 需要已知 term_id |
已知 term_id 的情况下 |
slug |
方便,易于使用 | 需要查询数据库,性能略低于 term_id |
需要通过 slug 查找分类术语的情况下 |
name |
更人性化,可以使用分类术语的名称进行查询 | 需要查询数据库,性能略低于 term_id 和 slug |
需要通过分类术语的名称查找分类术语的情况下 |
希望今天的分享对大家有所帮助。记住,深入理解 WordPress 的源码,就像拥有了一张藏宝图,可以帮助你更快地找到你想要的信息,并构建更高效的网站。 谢谢大家!