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_field
action,并返回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 的源码,就像拥有了一张藏宝图,可以帮助你更快地找到你想要的信息,并构建更高效的网站。 谢谢大家!