各位技术大咖,大家好!今天我们来聊聊 WordPress 里一个神奇的函数 get_term_by()
,这玩意儿就像个分类术语界的福尔摩斯,能根据各种线索帮你找到你想找的分类、标签等等。准备好了吗?咱们开始探秘之旅!
一、get_term_by()
:分类术语的侦探
想象一下,你需要在一个庞大的图书馆(WordPress 的数据库)里找到一本特定的书(一个分类术语)。你知道书名,或者作者,或者ISBN编号。get_term_by()
就像图书馆的管理员,你告诉它你掌握的线索,它就能帮你找到那本书。
简单来说,get_term_by()
函数允许你根据术语的特定属性(例如名称、slug、ID)来检索术语对象。这比直接查询数据库要方便得多,因为它已经帮你处理了复杂的 SQL 查询和数据处理。
二、get_term_by()
的语法和参数
get_term_by()
的语法如下:
<?php
get_term_by( string $field, string|int $value, string|array $taxonomy = 'category', string $output = OBJECT, string $filter = 'raw' );
?>
$field
(string, required): 你要搜索的字段。可以是'id'
,'slug'
,'name'
, 或'term_taxonomy_id'
。 如果传了其他字段,函数会直接返回false
。$value
(string|int, required): 要搜索的字段的值。例如,如果你$field
是'name'
,$value
就是你要搜索的名称。$taxonomy
(string|array, optional): 术语所属的分类法。默认为'category'
。可以是单个分类法名称(例如'post_tag'
)或分类法名称数组(例如array( 'category', 'post_tag' )
)。$output
(string, optional): 输出格式。默认为OBJECT
,返回一个标准的对象。可以设置为ARRAY_A
(关联数组)、ARRAY_N
(数字索引数组)或OBJECT
(对象)。$filter
(string, optional): 在返回数据之前应用的过滤器。默认为'raw'
,表示不进行任何过滤。
三、get_term_by()
源码剖析:一步一步揭秘
现在,让我们深入 wp-includes/taxonomy.php
文件,看看 get_term_by()
的源码。这部分是重点,请集中注意力!
function get_term_by( string $field, string|int $value, string|array $taxonomy = 'category', string $output = OBJECT, string $filter = 'raw' ) {
global $wpdb;
if ( ! in_array( $field, array( 'id', 'slug', 'name', 'term_taxonomy_id' ), true ) ) {
return false;
}
if ( empty( $taxonomy ) || ! taxonomy_exists( $taxonomy ) ) {
return false;
}
$taxonomies = wp_parse_args( $taxonomy );
$taxonomies = array_map( 'sanitize_key', $taxonomies );
$taxonomies = "'" . implode( "', '", $taxonomies ) . "'";
$value = sanitize_text_field( $value );
$select = '';
switch ( $field ) {
case 'id':
$id = absint( $value );
$select = "WHERE t.term_id = '$id'";
break;
case 'slug':
$slug = sanitize_title( $value );
$select = "WHERE t.slug = '$slug'";
break;
case 'name':
$name = trim( $value );
$name = esc_sql( $name );
$select = "WHERE t.name = '$name'";
break;
case 'term_taxonomy_id':
$term_taxonomy_id = absint( $value );
$select = "WHERE tt.term_taxonomy_id = '$term_taxonomy_id'";
break;
default:
return false;
}
$query = "SELECT t.*, tt.* FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy IN ($taxonomies) $select";
$term = $wpdb->get_row( $query );
if ( ! $term ) {
return false;
}
// Convert to output format.
return get_term( $term, $taxonomy, $output, $filter );
}
让我们一步一步解读这段代码:
-
参数验证 (Lines 4-12):
- 首先,它检查
$field
参数是否有效。$field
必须是'id'
,'slug'
,'name'
, 或'term_taxonomy_id'
之一。 如果不是,函数直接返回false
,表示搜索失败。 - 然后,它检查
$taxonomy
是否为空或者是否存在。如果分类法不存在,函数也返回false
。
- 首先,它检查
-
构建查询条件 (Lines 14-38):
wp_parse_args()
将$taxonomy
参数解析为数组,即使它是一个字符串。array_map( 'sanitize_key', $taxonomies )
对分类法名称进行清理,确保它们是有效的键。implode()
将分类法名称数组转换为一个字符串,用逗号分隔,并用单引号括起来,以便在 SQL 查询中使用。sanitize_text_field()
对$value
进行清理,防止 XSS 攻击。- 接下来,根据
$field
的值,构建 SQL 查询的WHERE
子句。例如,如果$field
是'id'
,则$select
变量将被设置为"WHERE t.term_id = '$id'"
。 这里会对$value
进行相应的清理和转义,确保安全性。
-
执行数据库查询 (Line 40):
$query
变量包含最终的 SQL 查询语句。这个查询语句连接了wp_terms
和wp_term_taxonomy
表,并根据$taxonomy
和$select
变量中的条件筛选结果。$wpdb->get_row( $query )
执行 SQL 查询,并返回一个包含结果的行对象。 如果没有找到匹配的术语,则返回null
。
-
处理查询结果 (Lines 42-48):
- 如果查询结果为空(
! $term
),函数返回false
。 - 如果查询结果不为空,函数调用
get_term()
函数,将查询结果转换为指定的输出格式(OBJECT
,ARRAY_A
, 或ARRAY_N
)并应用过滤器。
- 如果查询结果为空(
四、get_term()
函数:术语对象的塑造者
get_term_by()
最终调用了 get_term()
函数来格式化结果。 让我们简单看看 get_term()
的作用(完整源码比较长,这里只关注关键部分):
get_term()
主要负责:
- 从数据库结果构建术语对象: 它将数据库查询返回的原始数据(来自
$wpdb->terms
和$wpdb->term_taxonomy
表)合并成一个更有用的术语对象。 - 应用过滤器: 它应用各种过滤器,允许开发者修改术语对象的属性。 例如,
'get_term'
过滤器允许你修改任何术语的属性,而'get_{$taxonomy}'
过滤器允许你只修改特定分类法的术语的属性。 - 缓存: 它将术语对象缓存在内存中,以便后续的请求可以更快地检索术语。
五、使用示例:实战演练
让我们通过一些例子来看看如何使用 get_term_by()
。
-
根据名称获取分类:
$term = get_term_by( 'name', '我的分类', 'category' ); if ( $term ) { echo '分类 ID: ' . $term->term_id; echo '分类 Slug: ' . $term->slug; } else { echo '未找到分类!'; }
-
根据 Slug 获取标签:
$term = get_term_by( 'slug', 'my-tag', 'post_tag' ); if ( $term ) { echo '标签 ID: ' . $term->term_id; echo '标签名称: ' . $term->name; } else { echo '未找到标签!'; }
-
根据 ID 获取自定义分类法的术语:
假设你有一个自定义分类法叫做
'product_category'
。$term = get_term_by( 'id', 123, 'product_category' ); if ( $term ) { echo '自定义分类 ID: ' . $term->term_id; echo '自定义分类名称: ' . $term->name; } else { echo '未找到自定义分类!'; }
-
指定输出格式为数组:
$term = get_term_by( 'name', '我的分类', 'category', ARRAY_A ); if ( is_array( $term ) ) { echo '分类 ID: ' . $term['term_id']; echo '分类 Slug: ' . $term['slug']; } else { echo '未找到分类!'; }
六、注意事项和最佳实践
- 性能: 尽量使用
'id'
或'term_taxonomy_id'
进行搜索,因为这些字段是索引字段,查询速度更快。 使用'name'
或'slug'
查询会慢一些,因为数据库需要进行字符串比较。 - 安全性:
get_term_by()
函数会对输入进行清理,但你仍然应该注意防止 SQL 注入攻击。 始终对用户输入进行验证和清理。 - 缓存: WordPress 会缓存术语对象,所以多次调用
get_term_by()
函数不会对性能产生太大的影响。 但是,如果你修改了术语的属性,你可能需要清除缓存才能看到更改。 - 错误处理: 始终检查
get_term_by()
函数的返回值。 如果函数返回false
,表示没有找到匹配的术语。
七、get_term_by()
与其他函数的比较
函数 | 描述 | 使用场景 |
---|---|---|
get_term_by() |
根据指定的字段和值检索术语对象。 | 当你知道术语的特定属性(例如名称、slug、ID)时。 |
get_term() |
根据术语 ID 或术语对象检索术语对象。 | 当你已经知道术语 ID 或已经有一个术语对象时。 |
get_terms() |
检索多个术语对象。 | 当你需要检索多个术语,例如获取所有分类或所有标签时。 |
wp_get_post_terms() |
检索与特定文章关联的术语。 | 当你需要获取与特定文章关联的分类、标签或自定义分类法的术语时。 |
直接使用 $wpdb 查询 |
直接执行 SQL 查询来检索术语。 | 当你需要执行复杂的查询,get_term_by() 或其他 WordPress 函数无法满足你的需求时。(不推荐,除非非常必要) |
八、高级应用:自定义过滤器
get_term()
函数应用了多个过滤器,允许你修改术语对象的属性。 这为你提供了很大的灵活性。
例如,你可以使用 'get_term'
过滤器来修改所有术语的描述:
add_filter( 'get_term', 'my_custom_term_description', 10, 2 );
function my_custom_term_description( $term, $taxonomy ) {
$term->description = '这是一个自定义的描述!';
return $term;
}
或者,你可以使用 'get_{$taxonomy}'
过滤器来修改特定分类法的术语的属性:
add_filter( 'get_category', 'my_custom_category_description', 10, 2 );
function my_custom_category_description( $term, $taxonomy ) {
$term->description = '这是一个自定义的分类描述!';
return $term;
}
九、总结
get_term_by()
是 WordPress 中一个非常有用的函数,它允许你根据术语的特定属性来检索术语对象。 掌握 get_term_by()
函数的用法和原理,可以帮助你更好地管理和操作 WordPress 的分类和标签。 记住,理解源码是提升技能的关键!
希望今天的讲座对大家有所帮助!下次再见!