各位观众,欢迎来到今天的 WordPress 源码探秘讲座!今天我们要聊的是 WordPress 分类术语的“生老病死”——也就是 wp_insert_term()
和 wp_delete_term()
这两个函数。
咱们先轻松一下,想象一下:你在 WordPress 站点上创建了一个新的分类“编程语言”,或者决定清理掉一个不再使用的标签“冷门技术”。这些动作背后,都是这两个函数在默默工作。
那么,它们到底是如何操作数据库,又是如何清理缓存,以保证我们的站点运行顺畅的呢?别急,咱们这就一层层剥开它们神秘的面纱!
一、wp_insert_term()
:新生命的诞生
wp_insert_term()
函数的作用是插入一个新的分类术语到数据库中。让我们深入源码,看看它是如何实现的。
function wp_insert_term( $term, $taxonomy, $args = array() ) {
global $wpdb;
// 1. 参数校验和准备
$term = trim( $term );
$taxonomy = trim( $taxonomy );
if ( empty( $term ) || empty( $taxonomy ) ) {
return new WP_Error( 'empty_term_name', __( 'A name is required for this term.' ) );
}
if ( strlen( $term ) > 200 ) {
return new WP_Error( 'term_name_too_long', __( 'Term names must be less than 200 characters.' ) );
}
if ( term_exists( $term, $taxonomy ) ) {
return new WP_Error( 'term_exists', __( 'Term name already exists.' ) );
}
$defaults = array(
'description' => '',
'slug' => '',
'parent' => 0,
);
$args = wp_parse_args( $args, $defaults );
$description = trim( $args['description'] );
$slug = trim( $args['slug'] );
$parent = (int) $args['parent'];
// 2. Slug 处理
if ( empty( $slug ) ) {
$slug = sanitize_title( $term );
}
$slug = wp_unique_term_slug( $slug, (object) array(
'taxonomy' => $taxonomy,
'parent' => $parent,
) );
// 3. 数据库插入
$data = compact( 'name', 'slug' );
$format = array( '%s', '%s' );
$wpdb->insert( $wpdb->terms, $data, $format );
$term_id = (int) $wpdb->insert_id;
// 4. taxonomy 关系插入
$data = compact( 'term_id', 'taxonomy', 'description', 'parent' );
$format = array( '%d', '%s', '%s', '%d' );
$wpdb->insert( $wpdb->term_taxonomy, $data, $format );
$tt_id = (int) $wpdb->insert_id;
// 5. 清理缓存
clean_term_cache( $term_id, $taxonomy );
// 6. 返回结果
return array(
'term_id' => $term_id,
'term_taxonomy_id' => $tt_id,
);
}
咱们把这个函数分解成几个关键步骤:
-
参数校验和准备:
- 首先,函数会检查传入的术语名称和分类法是否为空,长度是否超过限制。
- 接着,它会检查该术语是否已经存在。如果存在,就返回一个错误。
- 然后,它会使用
wp_parse_args()
函数将传入的$args
参数与默认值合并,处理描述、slug 和父级分类。
-
Slug 处理:
- 如果用户没有指定 slug,函数会自动根据术语名称生成一个。
wp_unique_term_slug()
函数会确保生成的 slug 在当前分类法下是唯一的,避免冲突。
-
数据库插入 (wp_terms):
- 使用
$wpdb->insert()
函数将术语名称和 slug 插入到wp_terms
表中。 $wpdb->insert_id
记录了插入的ID。wp_terms
表存储了所有术语的基本信息,包括名称和 slug。
-- 示例:wp_terms 表结构 CREATE TABLE `wp_terms` ( `term_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(200) NOT NULL DEFAULT '', `slug` varchar(200) NOT NULL DEFAULT '', `term_group` bigint(10) NOT NULL DEFAULT '0', PRIMARY KEY (`term_id`), KEY `slug` (`slug`(191)), KEY `name` (`name`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
- 使用
-
taxonomy 关系插入 (wp_term_taxonomy):
- 使用
$wpdb->insert()
函数将术语 ID、分类法、描述和父级分类 ID 插入到wp_term_taxonomy
表中。 wp_term_taxonomy
表存储了术语与分类法之间的关系,以及一些额外的属性,比如描述和父级分类。
-- 示例:wp_term_taxonomy 表结构 CREATE TABLE `wp_term_taxonomy` ( `term_taxonomy_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, `term_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0', `taxonomy` varchar(32) NOT NULL DEFAULT '', `description` longtext NOT NULL, `parent` bigint(20) UNSIGNED NOT NULL DEFAULT '0', `count` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`term_taxonomy_id`), UNIQUE KEY `term_id_taxonomy` (`term_id`,`taxonomy`), KEY `taxonomy` (`taxonomy`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
- 使用
-
清理缓存:
- 调用
clean_term_cache()
函数清理与该术语相关的缓存。这是非常关键的一步,确保站点显示的是最新的数据。
- 调用
-
返回结果:
- 函数返回一个包含
term_id
和term_taxonomy_id
的数组。
- 函数返回一个包含
关于 clean_term_cache()
函数
clean_term_cache()
函数负责清理与特定术语相关的缓存。它主要清理以下缓存:
- 术语对象缓存:通过
clean_object_term_cache()
函数清理。 - 分类法缓存:清理与该分类法相关的缓存,确保分类法信息是最新的。
- 术语关系缓存:清理术语关系缓存,确保术语之间的关系正确。
总结:wp_insert_term()
的工作流程
步骤 | 描述 | 涉及函数/表 |
---|---|---|
1 | 参数校验和准备:检查术语名称、分类法是否为空,长度是否超过限制,以及术语是否已经存在。 | term_exists() , wp_parse_args() |
2 | Slug 处理:生成唯一的 slug,避免冲突。 | sanitize_title() , wp_unique_term_slug() |
3 | 数据库插入 (wp_terms):将术语名称和 slug 插入到 wp_terms 表中。 |
$wpdb->insert() , wp_terms |
4 | taxonomy 关系插入 (wp_term_taxonomy):将术语 ID、分类法、描述和父级分类 ID 插入到 wp_term_taxonomy 表中。 |
$wpdb->insert() , wp_term_taxonomy |
5 | 清理缓存:清理与该术语相关的缓存,确保站点显示的是最新的数据。 | clean_term_cache() |
6 | 返回结果:返回一个包含 term_id 和 term_taxonomy_id 的数组。 |
二、wp_delete_term()
:谢幕与告别
wp_delete_term()
函数的作用是从数据库中删除一个分类术语。让我们看看它是如何“优雅地”删除数据的。
function wp_delete_term( $term, $taxonomy, $args = array() ) {
global $wpdb;
// 1. 参数校验
$term = (int) $term;
if ( empty( $term ) ) {
return new WP_Error( 'invalid_term', __( 'Invalid term ID.' ) );
}
$taxonomy = trim( $taxonomy );
if ( empty( $taxonomy ) ) {
return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
}
// 2. 检查术语是否存在
$term_exists = term_exists( $term, $taxonomy );
if ( is_null( $term_exists ) ) {
return new WP_Error( 'invalid_term', __( 'Nonexistent term ID.' ) );
}
// 3. 处理默认参数
$defaults = array( 'force_default' => false );
$args = wp_parse_args( $args, $defaults );
$object_ids = array();
// 4. 删除前钩子
do_action( 'pre_delete_term', $term, $taxonomy );
// 5. 检查是否设置为默认分类,如果是,则拒绝删除(除非强制删除)
if ( 'category' === $taxonomy && get_option( 'default_category' ) == $term && ! $args['force_default'] ) {
return new WP_Error( 'default_category', __( 'You cannot delete the default category.' ) );
}
// 6. 删除术语关系
$tt_ids = $wpdb->get_col( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE term_id = %d AND taxonomy = %s", $term, $taxonomy ) );
foreach ( $tt_ids as $tt_id ) {
$object_ids = array_merge( $object_ids, (array) $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $tt_id ) ) );
wp_remove_object_terms( $object_ids, $term, $taxonomy ); //移除对象关联
do_action( 'delete_term_taxonomy', $tt_id, $taxonomy ); //删除term_taxonomy前钩子
$wpdb->delete( $wpdb->term_taxonomy, array( 'term_taxonomy_id' => $tt_id ) ); //删除term_taxonomy数据
do_action( 'deleted_term_taxonomy', $tt_id, $taxonomy ); //删除term_taxonomy后钩子
}
// 7. 删除术语本身
$result = $wpdb->delete( $wpdb->terms, array( 'term_id' => $term ) );
// 8. 清理缓存
clean_term_cache( $term );
// 9. 删除后钩子
do_action( 'delete_term', $term, $taxonomy );
// 10. 返回结果
return $result;
}
我们来分解一下这个函数的执行流程:
-
参数校验:
- 函数首先会将传入的术语 ID 转换为整数,并检查术语 ID 和分类法是否为空。
-
检查术语是否存在:
- 使用
term_exists()
函数检查要删除的术语是否存在。如果不存在,则返回一个错误。
- 使用
-
处理默认参数:
- 使用
wp_parse_args()
函数处理默认参数,主要是force_default
,用于强制删除默认分类。
- 使用
-
删除前钩子:
do_action( 'pre_delete_term', $term, $taxonomy )
,在删除术语之前执行的钩子,允许插件或主题执行自定义操作。
-
检查是否设置为默认分类:
- 如果尝试删除的是默认分类,并且没有设置
force_default
为true
,则拒绝删除。
- 如果尝试删除的是默认分类,并且没有设置
-
删除术语关系:
- 首先,从
wp_term_taxonomy
表中获取与该术语和分类法相关的所有term_taxonomy_id
。 - 然后,遍历这些
term_taxonomy_id
,执行以下操作:- 从
wp_term_relationships
表中获取与该term_taxonomy_id
相关的所有对象 ID。 - 使用
wp_remove_object_terms()
函数移除对象与该术语的关联。 do_action( 'delete_term_taxonomy', $tt_id, $taxonomy )
在删除term_taxonomy
记录前执行的钩子。- 使用
$wpdb->delete()
函数从wp_term_taxonomy
表中删除对应的记录。 do_action( 'deleted_term_taxonomy', $tt_id, $taxonomy )
在删除term_taxonomy
记录后执行的钩子。
- 从
- 首先,从
-
删除术语本身:
- 使用
$wpdb->delete()
函数从wp_terms
表中删除对应的术语。
- 使用
-
清理缓存:
- 调用
clean_term_cache()
函数清理与该术语相关的缓存。
- 调用
-
删除后钩子:
do_action( 'delete_term', $term, $taxonomy )
,在删除术语之后执行的钩子,允许插件或主题执行自定义操作。
-
返回结果:
- 返回
$wpdb->delete()
函数的执行结果,表示是否成功删除术语。
- 返回
关于 wp_remove_object_terms()
函数
wp_remove_object_terms()
函数用于移除对象与术语之间的关联。它从 wp_term_relationships
表中删除相关的记录。
总结:wp_delete_term()
的工作流程
步骤 | 描述 | 涉及函数/表 |
---|---|---|
1 | 参数校验:检查术语 ID 和分类法是否为空。 | |
2 | 检查术语是否存在:使用 term_exists() 函数检查要删除的术语是否存在。 |
term_exists() |
3 | 处理默认参数:使用 wp_parse_args() 函数处理默认参数,主要是 force_default ,用于强制删除默认分类。 |
wp_parse_args() |
4 | 删除前钩子:do_action( 'pre_delete_term', $term, $taxonomy ) ,在删除术语之前执行的钩子。 |
|
5 | 检查是否设置为默认分类:如果尝试删除的是默认分类,并且没有设置 force_default 为 true ,则拒绝删除。 |
get_option() |
6 | 删除术语关系:从 wp_term_taxonomy 表中获取与该术语和分类法相关的所有 term_taxonomy_id ,并遍历这些 ID,移除对象与该术语的关联,然后从 wp_term_taxonomy 表中删除对应的记录。 |
$wpdb->get_col() , wp_remove_object_terms() , $wpdb->delete() , wp_term_relationships , wp_term_taxonomy |
7 | 删除术语本身:使用 $wpdb->delete() 函数从 wp_terms 表中删除对应的术语。 |
$wpdb->delete() , wp_terms |
8 | 清理缓存:调用 clean_term_cache() 函数清理与该术语相关的缓存。 |
clean_term_cache() |
9 | 删除后钩子:do_action( 'delete_term', $term, $taxonomy ) ,在删除术语之后执行的钩子。 |
|
10 | 返回结果:返回 $wpdb->delete() 函数的执行结果,表示是否成功删除术语。 |
三、缓存的重要性
在 wp_insert_term()
和 wp_delete_term()
函数中,clean_term_cache()
函数都扮演着至关重要的角色。为什么缓存清理如此重要呢?
简单来说,缓存是为了提高网站的性能。WordPress 会将一些常用的数据(比如分类术语信息)存储在缓存中,这样下次访问时就不用再查询数据库,从而加快页面加载速度。
但是,如果数据库中的数据发生了变化(比如我们添加或删除了一个分类术语),而缓存没有及时更新,就会导致网站显示的是旧的数据,造成信息不一致。
因此,clean_term_cache()
函数的作用就是确保缓存与数据库中的数据保持同步,避免出现数据不一致的问题。
四、实战演练
为了更好地理解这两个函数的使用,我们来做几个简单的演示:
1. 创建一个新的分类术语
$result = wp_insert_term(
'WordPress 开发',
'category',
array(
'description' => '关于 WordPress 开发的文章',
'slug' => 'wordpress-development',
'parent' => 0,
)
);
if ( is_wp_error( $result ) ) {
echo 'Error: ' . $result->get_error_message();
} else {
echo '分类术语创建成功!Term ID: ' . $result['term_id'] . ', Term Taxonomy ID: ' . $result['term_taxonomy_id'];
}
2. 删除一个分类术语
$term_id = 5; // 替换为你要删除的术语 ID
$taxonomy = 'category';
$result = wp_delete_term( $term_id, $taxonomy );
if ( is_wp_error( $result ) ) {
echo 'Error: ' . $result->get_error_message();
} else {
echo '分类术语删除成功!';
}
五、总结
今天,我们一起深入探讨了 wp_insert_term()
和 wp_delete_term()
这两个 WordPress 函数的源码,了解了它们是如何操作数据库、处理 slug、以及清理缓存的。
希望通过今天的讲座,大家能够对 WordPress 分类术语的管理机制有更深入的理解,并在实际开发中更加得心应手。
下次有机会,我们再一起探索 WordPress 源码的其他奥秘! 谢谢大家!