wp_delete_post() │ WP 1.0.0
Trash or delete from the database specified post. The post can be of any type: post, attachment, page, custom type.
When the post is permanently deleted, all data associated with it are deleted also:
custom fields (post meta)
comments
communication with all taxonomies (terms associated with the post)
wp_delete_post() give all control to wp_trash_post() if:
the parameter $force_delete = false AND
post type is post or page AND
post is not trashed yet AND
the recycle bin is not disabled (see constant EMPTY_TRASH_DAYS ).
More notes
Uses action hook delete_post before deleting the post. Does not apply to the attachment post type.
Uses action hook deleted_post after the post has been deleted, but before the object cache has been cleared. Does not apply to the attachmentpost type.
Give all control to wp_delete_attachment() if the post type is attachment.
Does not remove attachments (images) associated with the post you want to delete.
Does not delete child or parent posts associated with the post to be deleted.
Returns
WP_Post|false|null . Post data on success, false or null on failure.
Usage
wp_delete_post( $post_id, $force_delete );
$post_id(int)
Post ID. (The default of 0 is for historical reasons; providing it is incorrect.).
$force_delete(true|false)
Whether to bypass Trash and force deletion.
Default: false
Examples
#1 Remove the default post "Hello World", which has ID = 1
$deleted = wp_delete_post(1);
print_r( $deleted );
/*
stdClass Object
(
[ID] => 1
[post_author] => 0
[post_date] => 2016-08-08 17:07:49
[post_date_gmt] => 2016-08-08 12:07:49
[post_content] =>
[post_title] => Hello World
[post_excerpt] =>
[post_status] => publish
[comment_status] => closed
[ping_status] => closed
[post_password] =>
[post_name] => hello-world
[to_ping] =>
[pinged] =>
[post_modified] => 2016-08-08 17:07:49
[post_modified_gmt] => 2016-08-08 12:07:49
[post_content_filtered] =>
[post_parent] => 0
[guid] => http://wp-example.com/hello-world
[menu_order] => 0
[post_type] => post
[post_mime_type] =>
[comment_count] => 0
[filter] => raw
)
*/
Add Your Own Example
Notes
Changelog
wp_delete_post() wp delete post code
WP 6.9.1
function wp_delete_post( $post_id = 0, $force_delete = false ) {
global $wpdb;
$post_id = (int) $post_id;
if ( $post_id <= 0 ) {
_doing_it_wrong( __FUNCTION__, __( 'The post ID must be greater than 0.' ), '6.9.0' );
return false;
}
$post = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id ) );
if ( ! $post ) {
return $post;
}
$post = get_post( $post );
if ( ! $force_delete
&& ( 'post' === $post->post_type || 'page' === $post->post_type )
&& 'trash' !== get_post_status( $post_id ) && EMPTY_TRASH_DAYS
) {
return wp_trash_post( $post_id );
}
if ( 'attachment' === $post->post_type ) {
return wp_delete_attachment( $post_id, $force_delete );
}
/**
* Filters whether a post deletion should take place.
*
* @since 4.4.0
*
* @param WP_Post|false|null $check Whether to go forward with deletion. Anything other than null will short-circuit deletion.
* @param WP_Post $post Post object.
* @param bool $force_delete Whether to bypass the Trash.
*/
$check = apply_filters( 'pre_delete_post', null, $post, $force_delete );
if ( null !== $check ) {
return $check;
}
/**
* Fires before a post is deleted, at the start of wp_delete_post().
*
* @since 3.2.0
* @since 5.5.0 Added the `$post` parameter.
*
* @see wp_delete_post()
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
do_action( 'before_delete_post', $post_id, $post );
delete_post_meta( $post_id, '_wp_trash_meta_status' );
delete_post_meta( $post_id, '_wp_trash_meta_time' );
wp_delete_object_term_relationships( $post_id, get_object_taxonomies( $post->post_type ) );
$parent_data = array( 'post_parent' => $post->post_parent );
$parent_where = array( 'post_parent' => $post_id );
if ( is_post_type_hierarchical( $post->post_type ) ) {
// Point children of this page to its parent, also clean the cache of affected children.
$children_query = $wpdb->prepare(
"SELECT * FROM $wpdb->posts WHERE post_parent = %d AND post_type = %s",
$post_id,
$post->post_type
);
$children = $wpdb->get_results( $children_query );
if ( $children ) {
$wpdb->update( $wpdb->posts, $parent_data, $parent_where + array( 'post_type' => $post->post_type ) );
}
}
// Do raw query. wp_get_post_revisions() is filtered.
$revision_ids = $wpdb->get_col(
$wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'revision'", $post_id )
);
// Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
foreach ( $revision_ids as $revision_id ) {
wp_delete_post_revision( $revision_id );
}
// Point all attachments to this post up one level.
$wpdb->update( $wpdb->posts, $parent_data, $parent_where + array( 'post_type' => 'attachment' ) );
wp_defer_comment_counting( true );
$comment_ids = $wpdb->get_col(
$wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d ORDER BY comment_ID DESC", $post_id )
);
foreach ( $comment_ids as $comment_id ) {
wp_delete_comment( $comment_id, true );
}
wp_defer_comment_counting( false );
$post_meta_ids = $wpdb->get_col(
$wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d ", $post_id )
);
foreach ( $post_meta_ids as $mid ) {
delete_metadata_by_mid( 'post', $mid );
}
/**
* Fires immediately before a post is deleted from the database.
*
* The dynamic portion of the hook name, `$post->post_type`, refers to
* the post type slug.
*
* @since 6.6.0
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
do_action( "delete_post_{$post->post_type}", $post_id, $post );
/**
* Fires immediately before a post is deleted from the database.
*
* @since 1.2.0
* @since 5.5.0 Added the `$post` parameter.
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
do_action( 'delete_post', $post_id, $post );
$result = $wpdb->delete( $wpdb->posts, array( 'ID' => $post_id ) );
if ( ! $result ) {
return false;
}
/**
* Fires immediately after a post is deleted from the database.
*
* The dynamic portion of the hook name, `$post->post_type`, refers to
* the post type slug.
*
* @since 6.6.0
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
do_action( "deleted_post_{$post->post_type}", $post_id, $post );
/**
* Fires immediately after a post is deleted from the database.
*
* @since 2.2.0
* @since 5.5.0 Added the `$post` parameter.
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
do_action( 'deleted_post', $post_id, $post );
clean_post_cache( $post );
if ( is_post_type_hierarchical( $post->post_type ) && $children ) {
foreach ( $children as $child ) {
clean_post_cache( $child );
}
}
wp_clear_scheduled_hook( 'publish_future_post', array( $post_id ) );
/**
* Fires after a post is deleted, at the conclusion of wp_delete_post().
*
* @since 3.2.0
* @since 5.5.0 Added the `$post` parameter.
*
* @see wp_delete_post()
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
do_action( 'after_delete_post', $post_id, $post );
return $post;
}
Related Functions