各位观众老爷们,晚上好!我是老码农,今天咱们来聊聊 WordPress 多站点(WPMU)中一个“辣手摧花”的函数:wpmu_delete_blog()
。 别看它名字平平无奇,干的可是“杀人放火”的勾当——删除整个子站点!
但是,它可不是简单粗暴地删个数据库就完事儿了,它得负责把所有与这个站点相关的数据都清理干净,保证“人走茶凉,不留痕迹”。 否则,留下来的“冤魂”(残留数据)会给系统带来各种问题。
所以,今天我们就来扒一扒 wpmu_delete_blog()
的源码,看看它是如何做到“斩草除根”的。 准备好了吗? 系好安全带,发车啦!
1. 函数入口,接收“死亡通知”
首先,让我们找到 wpmu_delete_blog()
的真身。 它位于 wp-includes/ms-functions.php
文件中。 打开文件,你会看到类似这样的代码:
/**
* Deletes a blog from the network.
*
* @since 2.0.0
*
* @param int $blog_id ID of the blog to delete.
* @param bool $drop Optional. Whether to completely drop the blog from the database.
* Default is true.
*
* @return bool True on success, false on failure.
*/
function wpmu_delete_blog( $blog_id, $drop = true ) {
global $wpdb, $current_site;
$blog_id = (int) $blog_id;
if ( ! is_numeric( $blog_id ) || $blog_id <= 1 ) {
return false;
}
/**
* Fires before a blog is deleted from the network.
*
* @since 2.0.0
*
* @param int $blog_id ID of the blog to delete.
* @param bool $drop Whether to completely drop the blog from the database.
*/
do_action( 'wpmu_delete_blog', $blog_id, $drop );
if ( is_super_admin() ) {
//... 后面还有很多代码
} else {
return false; // 只有超级管理员才能删除站点
}
//... 更多代码
}
这段代码做了什么呢?
- 接收参数: 接受两个参数:
$blog_id
(要删除的站点ID) 和$drop
(是否彻底删除数据库)。 - 参数校验: 检查
$blog_id
是否为有效的站点ID(必须是大于1的整数)。 - 权限验证: 只有超级管理员才能执行删除操作。
- 触发钩子:
do_action( 'wpmu_delete_blog', $blog_id, $drop );
这个非常重要,它允许其他插件或主题在站点删除之前执行一些自定义操作。 比如,清理与该站点相关的缓存、发送通知等等。 这就像给站点发了一张“死亡通知单”,告诉大家“伙计们,这家伙要凉了,赶紧收拾东西!”
2. 准备“行刑”:切换数据库
在真正删除数据之前,wpmu_delete_blog()
需要先切换到要删除的站点的数据库。 毕竟,数据都在那个数据库里呢!
$old_blog = $wpdb->blogid;
switch_to_blog( $blog_id ); //切换到要删除的站点数据库
这里,switch_to_blog()
函数就像一个“传送门”,把我们带到要删除的站点所在的数据库。
3. “大清洗”:开始删除数据
终于到了最关键的环节:删除数据! wpmu_delete_blog()
使用了一系列的函数和SQL语句来完成这个任务。 我们来逐一分析:
-
删除站点选项 (Options):
delete_option( 'cron' ); delete_option( 'recently_edited' ); delete_transient( 'random_seed' ); delete_transient( 'doing_cron' );
这些代码删除了站点的一些常用选项和瞬态数据(transients)。
cron
是计划任务相关的信息,recently_edited
是最近编辑的文章列表,random_seed
和doing_cron
是一些临时性的数据。 删除这些数据可以避免一些潜在的问题。 -
删除站点上的所有用户:
$users = get_users( array( 'blog_id' => $blog_id, 'fields' => 'ids', 'number' => 99999, ) ); if ( $users ) { foreach ( $users as $user_id ) { wp_delete_user( $user_id, $reassign = null ); } }
这段代码获取站点上的所有用户,然后逐个删除。
wp_delete_user()
函数负责删除用户数据。$reassign = null
表示删除用户时,不将用户发表的文章分配给其他用户。 这意味着这些文章也会被删除(因为它们属于被删除的用户)。 -
删除站点的上传文件:
$upload_dir = wp_upload_dir(); $dir = $upload_dir['basedir']; delete_files( $dir, true );
这段代码获取站点的上传目录,然后使用
delete_files()
函数删除该目录下的所有文件和子目录。delete_files()
函数是一个递归函数,它可以删除目录及其所有内容。true
参数表示强制删除。 -
删除站点上的所有文章、页面、自定义文章类型等内容:
$tables = array( 'posts', 'comments', 'term_relationships', 'termmeta' ); foreach ( $tables as $table ) { $wpdb->query( "DELETE FROM {$wpdb->$table} WHERE {$wpdb->$table}.{$wpdb->blogid_column} = '$blog_id'" ); } $wpdb->query( "DELETE FROM {$wpdb->terms} WHERE term_id NOT IN ( SELECT term_id FROM {$wpdb->term_taxonomy} )" ); $wpdb->query( "DELETE FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id NOT IN ( SELECT term_taxonomy_id FROM {$wpdb->term_relationships} )" );
这段代码删除了站点上的所有文章、评论、分类、标签等内容。 它遍历几个关键的数据表(
posts
,comments
,term_relationships
,termmeta
),然后使用DELETE
语句删除与该站点相关的数据。{$wpdb->blogid_column}
表示包含站点ID的列名,通常是blog_id
。 最后两行SQL语句用于清理terms
和term_taxonomy
表中孤立的数据。 -
删除站点相关的缓存:
wp_cache_flush();
wp_cache_flush()
函数用于清空站点缓存。 这可以确保删除操作的更改立即生效,避免出现缓存导致的数据不一致问题。
4. “终极审判”:彻底删除数据库
如果 $drop
参数为 true
(默认值),wpmu_delete_blog()
还会彻底删除该站点的数据库表。 这相当于把整个站点从数据库中抹去。
if ( $drop ) {
$prefix = $wpdb->get_blog_prefix( $blog_id );
$query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $prefix ) . '%' );
$tables = $wpdb->get_col( $query );
foreach ( $tables as $table ) {
$wpdb->query( "DROP TABLE IF EXISTS `$table`" );
}
}
这段代码首先获取该站点的表前缀(例如 wp_2_
),然后使用 SHOW TABLES LIKE
语句查找所有以该前缀开头的表。 最后,使用 DROP TABLE
语句逐个删除这些表。 注意,这里使用了反引号 (`) 来包裹表名,以防止表名中包含特殊字符导致SQL错误。
5. “善后处理”:恢复数据库并清理站点记录
删除完数据后,wpmu_delete_blog()
还需要做一些“善后处理”:
restore_current_blog(); // 恢复到之前的站点数据库
// Remove the blog from the blogs table
$wpdb->delete( $wpdb->blogs, array( 'blog_id' => $blog_id ) );
// Remove the blog from the sitemeta table
$wpdb->delete( $wpdb->sitemeta, array( 'site_id' => $current_site->id, 'meta_key' => 'blog_id', 'meta_value' => $blog_id ) );
clean_site_cache();
/**
* Fires after a blog is deleted from the network.
*
* @since 2.0.0
*
* @param int $blog_id ID of the deleted blog.
* @param bool $drop Whether the blog was completely dropped from the database.
*/
do_action( 'wpmu_delete_blog', $blog_id, $drop );
return true;
这段代码做了什么呢?
- 恢复数据库:
restore_current_blog()
函数恢复到之前的站点数据库。 这就像从“传送门”回来,回到主站点。 - 删除站点记录: 从
wp_blogs
表中删除该站点的记录,从wp_sitemeta
表中删除与该站点相关的元数据。 - 清理站点缓存:
clean_site_cache()
函数清理站点缓存。 - 触发钩子:
do_action( 'wpmu_delete_blog', $blog_id, $drop );
再次触发钩子,允许其他插件或主题在站点删除之后执行一些自定义操作。 这就像给站点办了一场“追悼会”,告诉大家“这家伙真的凉透了,可以盖棺定论了!”
6. 流程总结:
为了更好地理解 wpmu_delete_blog()
的工作流程,我们用一个表格来总结一下:
步骤 | 描述 | 相关代码 |
---|---|---|
1. 入口 | 接收站点ID和是否彻底删除的参数,进行参数校验和权限验证,触发删除前的钩子。 | wpmu_delete_blog( $blog_id, $drop = true ) , do_action( 'wpmu_delete_blog', $blog_id, $drop ); |
2. 切换数据库 | 切换到要删除的站点的数据库。 | switch_to_blog( $blog_id ); |
3. 删除数据 | 删除站点选项、用户、上传文件、文章、评论、分类、标签等内容,清理缓存。 | delete_option() , delete_transient() , wp_delete_user() , delete_files() , $wpdb->query( "DELETE FROM ...") , wp_cache_flush() |
4. 删除数据库 | 如果 $drop 参数为 true ,则彻底删除该站点的数据库表。 |
$wpdb->query( "DROP TABLE IF EXISTS $table" ) |
5. 善后处理 | 恢复到之前的站点数据库,删除 wp_blogs 表和 wp_sitemeta 表中的站点记录,清理站点缓存,触发删除后的钩子。 |
restore_current_blog() , $wpdb->delete() , clean_site_cache() , do_action( 'wpmu_delete_blog', $blog_id, $drop ); |
6. 返回结果 | 返回 true 表示删除成功,false 表示删除失败。 |
return true; 或 return false; |
7. 注意事项:
- 谨慎操作:
wpmu_delete_blog()
是一个高危函数,使用前务必备份数据! 一旦删除,数据就无法恢复了。 - 理解
$drop
参数:$drop
参数决定是否彻底删除数据库。 如果只想删除站点数据,但保留数据库表,可以将$drop
设置为false
。 - 利用钩子:
wpmu_delete_blog
钩子允许你在站点删除前后执行自定义操作。 这对于清理插件或主题的残留数据非常有用。 - 性能考虑: 删除站点可能需要很长时间,特别是对于数据量大的站点。 建议在服务器空闲时执行删除操作。
8. 总结:
wpmu_delete_blog()
函数是 WordPress 多站点中一个非常重要的函数,它负责删除子站点及其相关的所有数据。 通过分析源码,我们可以深入了解它的工作原理,以及如何安全有效地使用它。 希望今天的讲座对你有所帮助!
下次再见!