各位观众老爷们,晚上好!今天咱们来聊聊 WordPress 里的一个“寻宝神器”—— get_term_by()
函数。别看它名字平平无奇,但它能根据你提供的各种线索,在分类法(Taxonomy)的茫茫大海中,精确地找到你想要的分类术语(Term)。
咱们要深入剖析一下它的源码,看看它到底是怎么做到“指哪打哪”的。准备好了吗?咱们这就开始!
1. get_term_by()
函数的真面目
首先,让我们来认识一下 get_term_by()
函数的基本结构。在 WordPress 的 wp-includes/taxonomy.php
文件中,你能找到它的身影。它的函数原型如下:
function get_term_by( string $field, string|int $value, string|array $taxonomy = 'category', string $output = OBJECT, string $filter = 'raw' ): WP_Term|false|null {
// ...函数体...
}
$field
:指定要搜索的字段。比如 ‘id’,’slug’,’name’ 等等。$value
:要搜索的字段对应的值。$taxonomy
:可选参数,指定分类法。默认为 ‘category’。可以是一个字符串,也可以是一个包含多个分类法名称的数组。$output
:可选参数,指定返回值的类型。默认为OBJECT
,返回一个WP_Term
对象。还可以是ARRAY_A
(关联数组),ARRAY_N
(索引数组), 或者OBJECT_K
(键为ID的对象数组,WordPress 4.7.0新增)。$filter
:可选参数,指定如何过滤返回值。默认为 ‘raw’,不进行任何过滤。
2. 源码剖析:一步一步揭秘
接下来,让我们深入 get_term_by()
函数的源码,看看它是如何工作的。为了方便理解,我将代码拆解成几个关键步骤,并加上详细的注释。
function get_term_by( string $field, string|int $value, string|array $taxonomy = 'category', string $output = OBJECT, string $filter = 'raw' ): WP_Term|false|null {
global $wpdb;
// 1. 参数校验和准备
$taxonomies = (array) $taxonomy; // 将分类法转换为数组,方便处理
$single_taxonomy = ( 1 === count( $taxonomies ) ); // 标记是否只有一个分类法
$taxonomy = reset( $taxonomies ); // 获取第一个分类法,用于某些情况下的单分类法操作
// 2. 检查缓存
$term = wp_cache_get( "$field:$value:$taxonomy", 'terms' ); // 尝试从缓存中获取 Term
if ( false !== $term ) {
/** This filter is documented in wp-includes/taxonomy.php */
return apply_filters( 'get_term', $term, $taxonomy, $filter ); // 如果缓存命中,直接返回
}
// 3. 构建 SQL 查询语句
$select = 't.*, tt.*'; // 选择的字段
$from = "{$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id"; // 表连接
$where = $wpdb->prepare( 'tt.taxonomy IN (%s)', implode( "','", array_map( 'esc_sql', $taxonomies ) ) ); // 分类法限制
switch ( $field ) { // 根据不同的 $field 构建不同的 WHERE 子句
case 'id':
$id = intval( $value );
$where .= $wpdb->prepare( ' AND t.term_id = %d', $id );
break;
case 'slug':
$slug = sanitize_title( $value );
$where .= $wpdb->prepare( ' AND t.slug = %s', $slug );
break;
case 'name':
$name = trim( $value );
$where .= $wpdb->prepare( ' AND t.name = %s', $name );
break;
case 'term_taxonomy_id':
$term_taxonomy_id = intval( $value );
$where .= $wpdb->prepare( ' AND tt.term_taxonomy_id = %d', $term_taxonomy_id );
break;
default:
return false; // 如果 $field 不支持,返回 false
}
$orderby = 't.name ASC'; // 默认排序
$query = "SELECT $select FROM $from WHERE $where ORDER BY $orderby"; // 完整的 SQL 查询语句
// 4. 执行查询
$term = $wpdb->get_row( $query ); // 执行查询,获取结果
if ( ! $term ) {
return false; // 如果没有找到 Term,返回 false
}
// 5. 处理结果
$term = sanitize_term( $term, $taxonomy, $filter ); // 对 Term 进行清理和过滤
$term = new WP_Term( $term );
wp_cache_set( "$field:$value:$taxonomy", $term, 'terms' ); // 将 Term 存入缓存
$term = apply_filters( 'get_term', $term, $taxonomy, $filter ); // 应用 'get_term' 过滤器
// 6. 格式化输出
if ( OBJECT === $output ) {
return $term; // 返回 WP_Term 对象
} elseif ( ARRAY_A === $output ) {
return get_object_vars( $term ); // 返回关联数组
} elseif ( ARRAY_N === $output ) {
return array_values( get_object_vars( $term ) ); // 返回索引数组
} elseif ( OBJECT_K === $output ) {
return array( $term->term_id => $term );
}
return $term; // 默认返回 WP_Term 对象
}
3. 代码解读:逐行分析
- 参数校验和准备: 首先,函数会将传入的
$taxonomy
参数转换为数组,即使你只传入了一个分类法,也会被转换成数组,方便后续的统一处理。 还会判断是不是单分类,方便后续逻辑处理。 - 缓存检查: 这是提高性能的关键一步。函数会尝试从 WordPress 的对象缓存中获取 Term。缓存的键是根据
$field
,$value
, 和$taxonomy
生成的。如果缓存命中,直接返回缓存中的 Term,避免重复查询数据库。 - 构建 SQL 查询语句: 这是整个函数的核心部分。函数会根据传入的
$field
参数,动态构建 SQL 查询语句的 WHERE 子句。$select
:指定要查询的字段,包括terms
表和term_taxonomy
表中的字段。$from
:指定要查询的表,这里使用了INNER JOIN
连接terms
表和term_taxonomy
表。$where
:这是最重要的部分。函数会根据$field
的值,构建不同的 WHERE 子句。- 如果
$field
是 ‘id’,则查询t.term_id
字段。 - 如果
$field
是 ‘slug’,则查询t.slug
字段。 - 如果
$field
是 ‘name’,则查询t.name
字段。 - 如果
$field
是 ‘term_taxonomy_id’,则查询tt.term_taxonomy_id
字段。 - 如果
$field
是其他值,则返回false
,表示不支持该字段的搜索。
- 如果
- 执行查询: 使用
$wpdb->get_row()
函数执行 SQL 查询,获取结果。 - 处理结果: 如果查询结果不为空,则会对 Term 进行清理和过滤,防止 XSS 攻击。还会构建
WP_Term
对象。 - 存入缓存: 将查询结果存入缓存,以便下次使用。
- 应用过滤器: 应用 ‘get_term’ 过滤器,允许其他插件或主题修改 Term 对象。
- 格式化输出: 根据
$output
参数,将 Term 对象格式化为不同的类型,包括OBJECT
(默认),ARRAY_A
(关联数组),ARRAY_N
(索引数组),或者OBJECT_K
(键为ID的对象数组)。
4. 动态构建查询条件:$wpdb->prepare()
的妙用
在构建 SQL 查询语句的过程中,$wpdb->prepare()
函数起到了至关重要的作用。它主要有两个作用:
- 防止 SQL 注入:
$wpdb->prepare()
函数会对传入的参数进行转义,防止 SQL 注入攻击。 - 格式化 SQL 语句:
$wpdb->prepare()
函数可以根据参数类型,自动格式化 SQL 语句。
例如,以下代码:
$id = intval( $value );
$where .= $wpdb->prepare( ' AND t.term_id = %d', $id );
$wpdb->prepare()
函数会将 $id
参数转换为整数,并将其插入到 SQL 语句中。这样可以确保 SQL 语句的安全性,并提高查询效率。
5. 实际应用:代码示例
为了更好地理解 get_term_by()
函数的用法,我们来看几个实际的代码示例。
- 根据 ID 获取分类术语:
$term = get_term_by( 'id', 10, 'category' );
if ( $term ) {
echo '分类术语名称:' . $term->name;
} else {
echo '未找到分类术语';
}
- 根据 Slug 获取分类术语:
$term = get_term_by( 'slug', 'uncategorized', 'category' );
if ( $term ) {
echo '分类术语ID:' . $term->term_id;
} else {
echo '未找到分类术语';
}
- 根据 Name 获取分类术语:
$term = get_term_by( 'name', '未分类', 'category' );
if ( $term ) {
echo '分类术语Slug:' . $term->slug;
} else {
echo '未找到分类术语';
}
- 在多个分类法中搜索:
$taxonomies = array( 'category', 'post_tag' );
$term = get_term_by( 'name', '测试', $taxonomies );
if ( $term ) {
echo '分类术语所属分类法:' . $term->taxonomy;
} else {
echo '未找到分类术语';
}
6. 注意事项:使用技巧
- 优先使用 ID 搜索: 如果你知道分类术语的 ID,最好使用 ID 进行搜索,因为 ID 是唯一的,查询效率最高。
- 注意 Slug 的大小写: Slug 是区分大小写的,所以要确保你提供的 Slug 与数据库中的 Slug 完全一致。
- 利用缓存:
get_term_by()
函数会自动使用缓存,但如果你需要频繁地获取同一个分类术语,可以手动使用wp_cache_get()
和wp_cache_set()
函数来管理缓存,以提高性能。 - 理解
$output
参数: 根据你的需求选择合适的$output
参数。如果你只需要分类术语的少量信息,可以使用ARRAY_A
或ARRAY_N
,这样可以减少内存占用。 - 注意
$filter
参数: 默认情况下,get_term_by()
函数会对分类术语进行清理和过滤。如果你需要获取原始的分类术语数据,可以将$filter
参数设置为 ‘raw’。
7. get_term_by()
和 get_term()
的区别
有些朋友可能会问,get_term_by()
和 get_term()
函数有什么区别呢?
函数 | 功能 | 参数 | 返回值 |
---|---|---|---|
get_term_by() |
根据指定的字段和值,获取分类术语 | $field (字段名), $value (字段值), $taxonomy (分类法), $output (输出格式), $filter (过滤器) |
WP_Term 对象, false (未找到), null (出错), 或者根据 $output 参数返回不同的格式 |
get_term() |
根据分类术语的 ID 或 Slug,获取分类术语 | $term (Term ID 或 Term Object), $taxonomy (分类法), $output (输出格式), $filter (过滤器) |
WP_Term 对象, false (未找到), WP_Error 对象 (出错), 或者根据 $output 参数返回不同的格式。 如果传入的 $term 是一个 WP_Error 对象,函数会直接返回该对象。 |
简单来说,get_term_by()
函数更加灵活,可以根据不同的字段进行搜索,而 get_term()
函数只能根据 ID 或 Slug 进行搜索。
8. 总结:get_term_by()
的价值
get_term_by()
函数是 WordPress 中一个非常实用且功能强大的函数。它允许你根据不同的条件,动态地查询和获取分类术语。通过深入理解其源码,我们可以更好地掌握其用法,并利用它来构建更高效、更灵活的 WordPress 应用程序。
希望今天的分享对大家有所帮助。如果有什么疑问,欢迎随时提问!咱们下期再见!