Updates a post with new post data.
Description
The date does not have to be set for drafts. You can set the date and it will not be overridden.
Parameters
$postarr
array|objectoptional- Post data. Arrays are expected to be escaped, objects are not. See wp_insert_post() for accepted arguments.
Default array.More Arguments from wp_insert_post( … $postarr )
An array of elements that make up a post to update or insert.
ID
intThe post ID. If equal to something other than 0, the post with that ID will be updated. Default 0.post_author
intThe ID of the user who added the post. Default is the current user ID.post_date
stringThe date of the post. Default is the current time.post_date_gmt
stringThe date of the post in the GMT timezone. Default is the value of$post_date
.post_content
stringThe post content. Default empty.post_content_filtered
stringThe filtered post content. Default empty.post_title
stringThe post title. Default empty.post_excerpt
stringThe post excerpt. Default empty.post_status
stringThe post status. Default'draft'
.post_type
stringThe post type. Default'post'
.comment_status
stringWhether the post can accept comments. Accepts'open'
or'closed'
.
Default is the value of'default_comment_status'
option.ping_status
stringWhether the post can accept pings. Accepts'open'
or'closed'
.
Default is the value of'default_ping_status'
option.post_password
stringThe password to access the post. Default empty.post_name
stringThe post name. Default is the sanitized post title when creating a new post.to_ping
stringSpace or carriage return-separated list of URLs to ping.
Default empty.pinged
stringSpace or carriage return-separated list of URLs that have been pinged. Default empty.post_parent
intSet this for the post it belongs to, if any. Default 0.menu_order
intThe order the post should be displayed in. Default 0.post_mime_type
stringThe mime type of the post. Default empty.guid
stringGlobal Unique ID for referencing the post. Default empty.import_id
intThe post ID to be used when inserting a new post.
If specified, must not match any existing post ID. Default 0.post_category
int[]Array of category IDs.
Defaults to value of the'default_category'
option.tags_input
arrayArray of tag names, slugs, or IDs. Default empty.tax_input
arrayAn array of taxonomy terms keyed by their taxonomy name.
If the taxonomy is hierarchical, the term list needs to be either an array of term IDs or a comma-separated string of IDs.
If the taxonomy is non-hierarchical, the term list can be an array that contains term names or slugs, or a comma-separated string of names or slugs. This is because, in hierarchical taxonomy, child terms can have the same names with different parent terms, so the only way to connect them is using ID. Default empty.meta_input
arrayArray of post meta values keyed by their post meta key. Default empty.page_template
stringPage template to use.
Default:
array()
$wp_error
booloptional- Whether to return a WP_Error on failure.
Default:
false
$fire_after_hooks
booloptional- Whether to fire the after insert hooks.
Default:
true
Source
function wp_update_post( $postarr = array(), $wp_error = false, $fire_after_hooks = true ) {
if ( is_object( $postarr ) ) {
// Non-escaped post was passed.
$postarr = get_object_vars( $postarr );
$postarr = wp_slash( $postarr );
}
// First, get all of the original fields.
$post = get_post( $postarr['ID'], ARRAY_A );
if ( is_null( $post ) ) {
if ( $wp_error ) {
return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
}
return 0;
}
// Escape data pulled from DB.
$post = wp_slash( $post );
// Passed post category list overwrites existing category list if not empty.
if ( isset( $postarr['post_category'] ) && is_array( $postarr['post_category'] )
&& count( $postarr['post_category'] ) > 0
) {
$post_cats = $postarr['post_category'];
} else {
$post_cats = $post['post_category'];
}
// Drafts shouldn't be assigned a date unless explicitly done so by the user.
if ( isset( $post['post_status'] )
&& in_array( $post['post_status'], array( 'draft', 'pending', 'auto-draft' ), true )
&& empty( $postarr['edit_date'] ) && ( '0000-00-00 00:00:00' === $post['post_date_gmt'] )
) {
$clear_date = true;
} else {
$clear_date = false;
}
// Merge old and new fields with new fields overwriting old ones.
$postarr = array_merge( $post, $postarr );
$postarr['post_category'] = $post_cats;
if ( $clear_date ) {
$postarr['post_date'] = current_time( 'mysql' );
$postarr['post_date_gmt'] = '';
}
if ( 'attachment' === $postarr['post_type'] ) {
return wp_insert_attachment( $postarr, false, 0, $wp_error );
}
// Discard 'tags_input' parameter if it's the same as existing post tags.
if ( isset( $postarr['tags_input'] ) && is_object_in_taxonomy( $postarr['post_type'], 'post_tag' ) ) {
$tags = get_the_terms( $postarr['ID'], 'post_tag' );
$tag_names = array();
if ( $tags && ! is_wp_error( $tags ) ) {
$tag_names = wp_list_pluck( $tags, 'name' );
}
if ( $postarr['tags_input'] === $tag_names ) {
unset( $postarr['tags_input'] );
}
}
return wp_insert_post( $postarr, $wp_error, $fire_after_hooks );
}
Examples
Before calling wp_update_post() it is necessary to create an array to pass the necessary elements. Unlike wp_insert_post() , it is only necessary to pass the ID of the post to be updated and the elements to be updated. The names of the elements should match those in the database.
If your updates are not working, there could be an error. It is a good idea to set $wp_error to true and display the error immediately after.
Categories
Categories need to be passed as an array of integers that match the category IDs in the database. This is the case even where only one category is assigned to the post.
Caution – Infinite loop
When executed by an action hooked into save_post (e.g. a custom metabox), wp_update_post() has the potential to create an infinite loop. This happens because (1) wp_update_post() results in save_post being fired and (2) save_post is called twice when revisions are enabled (first when creating the revision, then when updating the original post—resulting in the creation of endless revisions).
If you must update a post from code called by save_post, make sure to verify the post_type is not set to ‘revision’ and that the $post object does indeed need to be updated.
Likewise, an action hooked into edit_attachment can cause an infinite loop if it contains a function call to wp_update_post passing an array parameter with a key value of “ID” and an associated value that corresponds to an Attachment.
Note you will need to remove then add the hook, code sample modified from the API/Action reference: save_post
You can also update the meta at the same time (if needed)
Programmatically change “publish” (or “draft”) to “future” and schedule the post to be published tomorrow:
When setting the
post_date
, make sure to also set thepost_date_gmt
.When you are setting the post date on a ‘draft’, ‘pending’ or ‘auto-draft’ post status, also set
edit_date
to true, otherwise the post date won’t be changed.If you are losing backslashes from
post_content
field, usewp_slash
function to prepare the data:If you’re importing and then applying some updates with this function, it doesn’t recognize ‘import_id’ so remember to also use ‘ID’ too.
In any case, if you “import” with wp_insert_post and then use wp_update_post, you’re going to lose all your featured images and any additional categories you added between import/update will be lost. (The plugin “Featured Image From URL” solves the featured images problem, if it’s activated.)
Also, some of the documentation suggests that you can use an author’s name or a category’s name, but as far as I can tell, you can only use the id numbers for authors and categories when importing/updating content.
programmatically publish a post,