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
$postarrarray|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.
IDintThe post ID. If equal to something other than 0, the post with that ID will be updated. Default 0.post_authorintThe ID of the user who added the post. Default is the current user ID.post_datestringThe date of the post. Default is the current time.post_date_gmtstringThe date of the post in the GMT timezone. Default is the value of$post_date.post_contentstringThe post content. Default empty.post_content_filteredstringThe filtered post content. Default empty.post_titlestringThe post title. Default empty.post_excerptstringThe post excerpt. Default empty.post_statusstringThe post status. Default'draft'.post_typestringThe post type. Default'post'.comment_statusstringWhether the post can accept comments. Accepts'open'or'closed'.
Default is the value of'default_comment_status'option.ping_statusstringWhether the post can accept pings. Accepts'open'or'closed'.
Default is the value of'default_ping_status'option.post_passwordstringThe password to access the post. Default empty.post_namestringThe post name. Default is the sanitized post title when creating a new post.to_pingstringSpace or carriage return-separated list of URLs to ping.
Default empty.pingedstringSpace or carriage return-separated list of URLs that have been pinged. Default empty.post_parentintSet this for the post it belongs to, if any. Default 0.menu_orderintThe order the post should be displayed in. Default 0.post_mime_typestringThe mime type of the post. Default empty.guidstringGlobal Unique ID for referencing the post. Default empty.import_idintThe post ID to be used when inserting a new post.
If specified, must not match any existing post ID. Default 0.post_categoryint[]Array of category IDs.
Defaults to value of the'default_category'option.tags_inputarrayArray of tag names, slugs, or IDs. Default empty.tax_inputarrayAn 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_inputarrayArray of post meta values keyed by their post meta key. Default empty.page_templatestringPage template to use.
Default:
array() $wp_errorbooloptional- Whether to return a WP_Error on failure.
Default:
false $fire_after_hooksbooloptional- 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)
If you are losing backslashes from
post_contentfield, usewp_slashfunction to prepare the data: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_dateto true, otherwise the post date won’t be changed.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.
If you are rescheduling a previously published post, you will be moving the post_status from ‘publish’ to ‘future’ – this seems to require both the
post_date_gmtand your local time (post_date) passed into the function though it executes without complaint if you pass onlypost_date:If you neglect to specify the GMT date, the post will stay at ‘Published’ but the ‘Published’ date will be set to the future – yes, this really happens! There is a
get_gmt_from_date()function which works for theY-m-d H:i:sdate/time format only, so you have to be careful there.Some earlier posts include an
edit_date => trueparameter and suggest it is required to reschedule but I cannot find any information listed in the argument list about it on the related pages and I am running a task that runs rescheduling code without specifying it. I am using a custom post type so this might be one of those cases where things behave differently.programmatically publish a post,