各位靓仔靓女,早上好!今天咱们来聊聊WordPress里那个“辣手摧花”的函数——wp_delete_post()
。这个函数专门负责把那些你不喜欢的文章从你的网站上“请走”,而且它可不是简单的删除,还会把跟这篇文章相关的各种东西一并处理掉。
准备好了吗?咱们开始拆解这个“销毁大师”!
一、 初始:wp_delete_post()
是个啥?
首先,wp_delete_post()
位于 wp-includes/post.php
文件中。它的主要作用是:
- 删除指定的文章(及其修订版本)。
- 删除与该文章关联的元数据(自定义字段)。
- 删除与该文章关联的评论。
- 触发一系列 actions 和 filters,方便开发者进行扩展。
它的基本语法如下:
/**
* Deletes a post.
*
* @since 2.0.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param int $postid Post ID.
* @param bool $force_delete Optional. Whether to bypass trash and force deletion. Default false.
* @return WP_Post|false WP_Post on success, false on failure.
*/
function wp_delete_post( $postid, $force_delete = false ) {
// 函数体...
}
$postid
: 要删除的文章ID。$force_delete
: 一个布尔值,决定是否强制删除。true
表示直接删除,不经过回收站;false
(默认) 表示先移动到回收站。
二、 源码剖析:一步一步看它如何“毁尸灭迹”
咱们直接进入源码,看看 wp_delete_post()
内部是怎么运作的。为了方便阅读,我会把代码分成几个部分,并加上详细的注释。
function wp_delete_post( $postid, $force_delete = false ) {
global $wpdb;
$postid = absint( $postid );
if ( ! $postid ) {
return false;
}
$post = get_post( $postid );
if ( ! $post ) {
return false;
}
$post_type_object = get_post_type_object( $post->post_type );
if ( ! current_user_can( $post_type_object->cap->delete_post, $postid ) ) {
wp_die( __( 'Sorry, you are not allowed to delete this post.' ) );
}
if ( $post->post_type === 'attachment' ) {
return wp_delete_attachment( $postid, $force_delete );
}
/**
* Fires before a post is deleted, at the start of the 'wp_delete_post' function.
*
* @since 4.4.0
*
* @param int $postid Post ID.
*/
do_action( 'wp_delete_post', $postid );
if ( ! $force_delete ) {
return wp_trash_post( $postid );
}
/**
* Fires before a post is permanently deleted.
*
* @since 2.9.0
*
* @param int $postid Post ID.
*/
do_action( 'before_delete_post', $postid );
// 1. 删除评论
$comments = get_comments(
array(
'post_id' => $postid,
'number' => 0, // All comments.
'status' => 'all',
)
);
if ( $comments ) {
foreach ( $comments as $comment ) {
wp_delete_comment( $comment->comment_ID, true );
}
}
// 2. 删除文章的元数据(自定义字段)
delete_metadata( 'post', $postid, '', '', true );
// 3. 删除文章关联的术语关系 (term relationships)
wp_delete_object_term_relationships( $postid, get_object_taxonomies( $post->post_type ) );
// 4. 删除文章本身及其修订版本
$revisions = wp_get_post_revisions( $postid );
if ( $revisions ) {
foreach ( $revisions as $revision ) {
wp_delete_post( $revision->ID, true );
}
}
$result = $wpdb->delete( $wpdb->posts, array( 'ID' => $postid ) );
if ( ! $result ) {
return false;
}
// 5. 更新计数,如文章数量等
wp_update_post_term_count( get_object_taxonomies( $post->post_type ), $post->post_type );
clean_post_cache( $postid );
/**
* Fires after a post is permanently deleted.
*
* @since 2.2.0
*
* @param int $postid Post ID.
*/
do_action( 'deleted_post', $postid );
return $post;
}
让我们分解一下这个过程:
-
前置检查:
$postid = absint( $postid );
:确保文章 ID 是一个整数。get_post( $postid );
:验证文章是否存在。current_user_can( $post_type_object->cap->delete_post, $postid );
: 检查当前用户是否有权限删除该文章。权限检查非常重要,防止非法操作。- 如果文章类型是
attachment
(附件),则调用wp_delete_attachment()
函数来处理。因为附件的删除逻辑可能稍有不同,比如需要删除物理文件。
-
Action Hook (钩子):
do_action( 'wp_delete_post', $postid );
: 这是一个重要的扩展点。开发者可以通过这个 action hook 在文章删除之前执行自定义操作。比如,记录删除日志,发送通知等等。
-
是否进入回收站?
if ( ! $force_delete ) { return wp_trash_post( $postid ); }
:如果$force_delete
为false
(默认),则调用wp_trash_post()
函数将文章移动到回收站。wp_trash_post()
实际上只是更新了文章的状态,将其post_status
修改为trash
。 如果$force_delete
为true
,则跳过回收站,直接进入永久删除流程。
-
永久删除流程:
do_action( 'before_delete_post', $postid );
:另一个 action hook,在永久删除文章之前触发。
-
清理评论:
$comments = get_comments( array( 'post_id' => $postid, 'number' => 0, // All comments. 'status' => 'all', ) ); if ( $comments ) { foreach ( $comments as $comment ) { wp_delete_comment( $comment->comment_ID, true ); } }
- 首先,通过
get_comments()
函数获取与该文章关联的所有评论,包括已批准、待审核和垃圾评论。 - 然后,循环遍历这些评论,并使用
wp_delete_comment()
函数永久删除每个评论。true
参数表示强制删除,不进入评论回收站。
- 首先,通过
-
清理元数据(自定义字段):
delete_metadata( 'post', $postid, '', '', true );
delete_metadata()
函数用于删除与指定对象关联的元数据。'post'
表示要删除的是文章的元数据。$postid
是文章的 ID。''
表示删除所有元数据键 (meta_key)。如果指定了 meta_key,则只会删除匹配的元数据。''
表示删除所有 meta_value,空字符串表示不指定meta_value,也就是删除所有。true
表示忽略缓存。
这段代码会删除所有与该文章关联的自定义字段。 这对保持数据库的清洁非常重要。
-
清理文章的术语关系 (Term Relationships):
wp_delete_object_term_relationships( $postid, get_object_taxonomies( $post->post_type ) );
wp_delete_object_term_relationships()
函数用于删除文章与分类法 (taxonomy) 术语 (term) 之间的关系。$postid
是文章的 ID。get_object_taxonomies( $post->post_type )
获取该文章类型所关联的所有分类法的名称 (例如:category, post_tag)。
这段代码会删除文章与所有分类、标签等之间的关联。
-
清理修订版本:
$revisions = wp_get_post_revisions( $postid ); if ( $revisions ) { foreach ( $revisions as $revision ) { wp_delete_post( $revision->ID, true ); } }
wp_get_post_revisions()
函数获取文章的所有修订版本。- 循环遍历这些修订版本,并使用
wp_delete_post()
函数递归地删除每个修订版本。 注意,这里使用了$force_delete = true
,表示强制删除修订版本。 因为修订版本通常不需要进入回收站。
-
删除文章本身:
$result = $wpdb->delete( $wpdb->posts, array( 'ID' => $postid ) ); if ( ! $result ) { return false; }
- 这是真正删除文章记录的代码。
$wpdb->delete()
使用 WordPress 的数据库抽象层来执行 SQL DELETE 语句。 $wpdb->posts
表示要删除的表是wp_posts
表。array( 'ID' => $postid )
指定删除条件,即ID
等于$postid
的记录。- 如果删除失败,则返回
false
。
- 这是真正删除文章记录的代码。
-
更新计数:
wp_update_post_term_count( get_object_taxonomies( $post->post_type ), $post->post_type );
wp_update_post_term_count()
函数用于更新与该文章类型关联的分类法的术语计数。 例如,如果删除了属于某个分类的文章,则需要更新该分类下的文章数量。
-
清理缓存:
clean_post_cache( $postid );
clean_post_cache()
函数用于清理文章的缓存。 这可以确保在删除文章后,网站上的内容能够及时更新。
-
Action Hook:
do_action( 'deleted_post', $postid );
- 另一个 action hook,在文章永久删除后触发。
-
返回结果:
return $post;
- 如果一切顺利,则返回被删除的文章对象。
三、重点:wp_delete_attachment()
前面提到,如果删除的是附件,wp_delete_post()
会调用 wp_delete_attachment()
函数。 让我们简单看看这个函数:
function wp_delete_attachment( $post_id, $force_delete = false ) {
$post = get_post( $post_id );
if ( empty( $post ) ) {
return false;
}
if ( 'attachment' !== $post->post_type ) {
return false;
}
if ( ! current_user_can( 'delete_post', $post_id ) ) {
wp_die( __( 'Sorry, you are not allowed to delete this attachment.' ) );
}
if ( $force_delete ) {
/**
* Fires before an attachment is deleted.
*
* @since 2.1.0
*
* @param int $post_id Attachment ID.
*/
do_action( 'delete_attachment', $post_id );
$meta = wp_get_attachment_metadata( $post_id );
$file = get_attached_file( $post_id );
if ( wp_delete_post( $post_id, true ) ) {
if ( ! empty( $meta['sizes'] ) ) {
foreach ( $meta['sizes'] as $size ) {
$intermediate_file = str_replace( wp_basename( $file ), $size['file'], $file );
/** This filter is documented in wp-includes/functions.php */
$intermediate_file = apply_filters( 'wp_delete_file', $intermediate_file );
@unlink( $intermediate_file );
}
}
/** This filter is documented in wp-includes/functions.php */
$file = apply_filters( 'wp_delete_file', $file );
@unlink( $file );
/**
* Fires after an attachment is deleted.
*
* @since 2.1.0
*
* @param int $post_id Attachment ID.
*/
do_action( 'deleted_attachment', $post_id );
return true;
}
} else {
return wp_trash_post( $post_id );
}
return false;
}
wp_delete_attachment()
与 wp_delete_post()
的主要区别在于,它会尝试删除与附件关联的物理文件。
- 它获取附件的元数据 (
wp_get_attachment_metadata()
),其中包含了各种尺寸的缩略图信息。 - 它使用
unlink()
函数删除原始文件和所有缩略图。 - 在删除文件之前和之后,它会触发
wp_delete_file
filter 和delete_attachment
/deleted_attachment
actions,允许开发者进行自定义操作。
四、 总结:wp_delete_post()
的核心逻辑
为了更清晰地理解 wp_delete_post()
的工作流程,我们可以用表格来总结一下:
步骤 | 说明 |
---|---|
1. 前置检查 | 验证文章ID的有效性,检查文章是否存在,检查当前用户是否有权限删除该文章。如果是附件,则调用 wp_delete_attachment() 。 |
2. Action wp_delete_post |
允许开发者在文章删除之前执行自定义操作。 |
3. 回收站判断 | 如果 $force_delete 为 false ,则将文章移动到回收站 (更新 post_status 为 trash )。 |
4. Action before_delete_post |
允许开发者在文章永久删除之前执行自定义操作。 |
5. 删除评论 | 获取并删除与文章关联的所有评论。 |
6. 删除元数据 | 删除与文章关联的所有自定义字段。 |
7. 删除术语关系 | 删除文章与分类法术语之间的关联。 |
8. 删除修订版本 | 递归地删除文章的所有修订版本。 |
9. 删除文章记录 | 从 wp_posts 表中删除文章记录。 |
10. 更新计数 | 更新与文章类型关联的分类法的术语计数。 |
11. 清理缓存 | 清理文章的缓存。 |
12. Action deleted_post |
允许开发者在文章永久删除之后执行自定义操作。 |
13. 返回结果 | 返回被删除的文章对象。 |
五、 安全性考虑
在使用 wp_delete_post()
时,需要特别注意安全性。
- 权限控制: 务必进行严格的权限控制,确保只有授权用户才能删除文章。
current_user_can()
函数是你的好朋友。 - 数据备份: 在进行大规模删除操作之前,务必备份数据库。 万一操作失误,还可以恢复数据。
- 谨慎使用
$force_delete
: 除非你真的确定要永久删除文章,否则不要使用$force_delete = true
。 回收站是一个很好的安全网。 - 处理用户输入: 如果要根据用户输入的文章 ID 来删除文章,务必对输入进行验证和过滤,防止 SQL 注入等安全问题。
六、 总结
wp_delete_post()
是一个功能强大的函数,可以彻底删除文章及其相关数据。 了解它的工作原理,可以帮助我们更好地管理 WordPress 网站,并进行自定义扩展。 同时,也要注意安全性,避免误操作和潜在的安全风险。
好了,今天的“销毁大师”讲座就到这里。 希望大家有所收获! 下次有机会再和大家聊聊 WordPress 的其他有趣话题。