wp_insert_post( array $postarr, bool $wp_error = false, bool $fire_after_hooks = true ): int|WP_Error
- Since
- 1.0.0, 2.6.0, 4.2.0, 4.4.0, 5.6.0
- Source
wp-includes/post.php:4432
Create or update a post programmatically with wp_insert_post(), passing fields like post_title, post_status, post_type, meta_input, and tax_input. It returns the new post ID on success and 0 on failure, or a WP_Error when $wp_error is true. Supplying an ID key updates that post instead of inserting a new one; new posts default to a draft of type post.
Description
Parameters
$postarrarray- An array of elements that make up a post to update or insert.
$IDintdefault: 0The post ID. If equal to something other than 0, the post with that ID will be updated.$post_authorintdefault: is the current user IDThe ID of the user who added the post.$post_datestringdefault: is the current timeThe date of the post.$post_date_gmtstringdefault: is the value of $post_dateThe date of the post in the GMT timezone.$post_contentstringdefault: emptyThe post content.$post_content_filteredstringdefault: emptyThe filtered post content.$post_titlestringdefault: emptyThe post title.$post_excerptstringdefault: emptyThe post excerpt.$post_statusstringdefault: 'draft'The post status.$post_typestringdefault: 'post'The post type.$comment_statusstringdefault: is the value of 'default_comment_status' optionWhether the post can accept comments. Accepts 'open' or 'closed'.$ping_statusstringdefault: is the value of 'default_ping_status' optionWhether the post can accept pings. Accepts 'open' or 'closed'.$post_passwordstringdefault: emptyThe password to access the post.$post_namestringdefault: is the sanitized post title when creating a new postThe post name.$to_pingstringdefault: emptySpace or carriage return-separated list of URLs to ping.$pingedstringdefault: emptySpace or carriage return-separated list of URLs that have been pinged.$post_parentintdefault: 0Set this for the post it belongs to, if any.$menu_orderintdefault: 0The order the post should be displayed in.$post_mime_typestringdefault: emptyThe mime type of the post.$guidstringdefault: emptyGlobal Unique ID for referencing the post.$import_idintdefault: 0The post ID to be used when inserting a new post. If specified, must not match any existing post ID.$post_categoryint[]Array of category IDs. Defaults to value of the 'default_category' option.$tags_inputarraydefault: emptyArray of tag names, slugs, or IDs.$tax_inputarraydefault: emptyAn 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.$meta_inputarraydefault: emptyArray of post meta values keyed by their post meta key.$page_templatestringPage template to use.
$wp_errorbooloptional- Whether to return a WP_Error on failure. Default false.Default:
false $fire_after_hooksbooloptional- Whether to fire the after insert hooks. Default true.Default:
true
Return
int|WP_Error- The post ID on success. The value 0 or WP_Error on failure.
Examples
Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.
Create a draft post with meta and tags
meta_input and tags_input save related data in the same call, so no follow-up writes are needed.
$post_id = wp_insert_post( array(
'post_title' => 'Imported release notes',
'post_content' => 'What changed in this release.',
'post_status' => 'draft',
'post_author' => 1,
'tags_input' => array( 'featured' ),
'meta_input' => array( 'price' => '0.00' ),
), true );
if ( is_wp_error( $post_id ) ) {
echo 'Failed: ', $post_id->get_error_message();
} else {
echo "created post {$post_id}\n";
echo 'status: ', get_post_status( $post_id ), "\n";
echo 'price meta: ', get_post_meta( $post_id, 'price', true ), "\n";
echo 'tags: ', implode( ', ', wp_get_post_tags( $post_id, array( 'fields' => 'names' ) ) );
}Pass true as the second argument or failures come back as 0 instead of a WP_Error.
Publish a page once, without creating duplicates
wp_insert_post() always inserts, so an importer that runs twice creates two posts unless it checks first.
$slug = 'pricing';
$existing = get_page_by_path( $slug );
if ( $existing ) {
echo "already exists as page {$existing->ID}, nothing to do";
} else {
$id = wp_insert_post( array(
'post_title' => 'Pricing',
'post_name' => $slug,
'post_type' => 'page',
'post_status' => 'publish',
'post_parent' => 6,
'post_author' => 1,
), true );
echo is_wp_error( $id ) ? $id->get_error_message() : "created page {$id} under page 6";
}Press Run twice: the second run takes the guard branch.
Hooks fired · 15
15 hooks fire while wp_insert_post() runs, in this order:
- apply_filters( wp_insert_post_empty_content )filterline 4529 (+97 into the body)
Filters whether the post should be considered "empty".
- apply_filters( wp_insert_post_parent )filterline 4702 (+270 into the body)
Filters the post parent -- used to check for and prevent hierarchy loops.
- apply_filters( add_trashed_suffix_to_trashed_posts )filterline 4728 (+296 into the body)
Filters whether or not to add a `__trashed` suffix to trashed posts that match the name of the updated post.
- apply_filters( wp_insert_attachment_data )filterline 4796 (+364 into the body)
Filters attachment post data before it is updated in or added to the database.
- apply_filters( wp_insert_post_data )filterline 4811 (+379 into the body)
Filters slashed post data just before it is inserted into the database.
- do_action( pre_post_update )actionline 4826 (+394 into the body)
Fires immediately before an existing post is updated in the database.
- do_action( edit_attachment )actionline 5010 (+578 into the body)
Fires once an existing attachment has been updated.
- do_action( attachment_updated )actionline 5023 (+591 into the body)
Fires once an existing attachment has been updated.
- do_action( add_attachment )actionline 5033 (+601 into the body)
Fires once an attachment has been added.
- do_action( edit_post_{$post->post_type} )actionline 5056 (+624 into the body)
Fires once an existing post has been updated.
- do_action( edit_post )actionline 5066 (+634 into the body)
Fires once an existing post has been updated.
- do_action( post_updated )actionline 5079 (+647 into the body)
Fires once an existing post has been updated.
- do_action( save_post_{$post->post_type} )actionline 5099 (+667 into the body)
Fires once a post has been saved.
Uses · 48
- get_current_user_id()Gets the current user's ID.
- wp_parse_args()Merges user defined arguments into defaults array.
- sanitize_post()Sanitizes every post field.
- get_post()Retrieves post data given a post ID or post object.
- __()Retrieves the translation of $text.
- get_post_field()Retrieves data from a post field based on Post ID.
- post_type_supports()Checks a post type's support for a given feature.
- apply_filters()Calls the callback functions that have been added to a filter hook.
- get_option()Retrieves an option value based on an option name.
- get_post_type_object()Retrieves a post type object by name.
- current_user_can()Returns whether the current user has the specified capability.
- sanitize_title()Sanitizes a string into a slug, which can be used in URLs or HTML attributes.
Show all 48
- wp_resolve_post_date()Uses wp_checkdate to return a valid Gregorian-calendar value for post_date.
- get_post_stati()Gets a list of post statuses.
- get_gmt_from_date()Given a date in the timezone of the site, returns that date in UTC.
- current_time()Retrieves the current time based on specified type.
- get_default_comment_status()Gets the default comment status for a post type.
- sanitize_trackback_urls()Sanitizes space or carriage return separated URLs that are used to send trackbacks.
- get_post_meta()Retrieves a post meta field for the given post ID.
- delete_post_meta()Deletes a post meta field for the given post ID.
- wp_add_trashed_suffix_to_post_name_for_trashed_posts()Adds a suffix if any trashed posts have a given slug.
- wp_add_trashed_suffix_to_post_name_for_post()Adds a trashed suffix for a given post.
- wp_unique_post_slug()Computes a unique slug for the post, when given the desired slug and some post details.
- wp_encode_emoji()Converts emoji characters to their equivalent HTML entity.
- wp_unslash()Removes slashes from a string or recursively removes slashes from strings within an array.
- do_action()Calls the callback functions that have been added to an action hook.
- clean_post_cache()Will clean the post in the cache.
- is_object_in_taxonomy()Determines if the given object type is associated with the given taxonomy.
- wp_set_post_categories()Sets categories for a post.
- wp_set_post_tags()Sets the tags for a post.
- get_object_taxonomies()Returns the names or objects of the taxonomies which are registered for the requested object or object type, such as a post object or post type name.
- wp_get_object_terms()Retrieves the terms associated with the given object(s), in the supplied taxonomies.
- get_taxonomy()Retrieves the taxonomy object of $taxonomy.
- _doing_it_wrong()Marks something as being incorrectly called.
- wp_set_post_terms()Sets the terms for a post.
- update_post_meta()Updates a post meta field based on the given post ID.
- get_permalink()Retrieves the full permalink for the current post or post ID.
- update_attached_file()Updates attachment file path based on attachment ID.
- add_post_meta()Adds a meta field to the given post.
- current_theme_supports()Checks a theme's support for a given feature.
- wp_attachment_is()Verifies an attachment is of a given type.
- delete_post_thumbnail()Removes the thumbnail (featured image) from the given post.
- set_post_thumbnail()Sets the post thumbnail (featured image) for the given post.
- wp_get_theme()Gets a WP_Theme object for a theme.
- wp_transition_post_status()Fires actions related to the transitioning of a post's status.
- wp_after_insert_post()Fires actions after a post, its terms and meta data has been saved.
- WP_Error::__construct()Initializes the error.
- wp_get_theme()::get_page_templates()
Used by · 21
- WP_Customize_Manager::save_changeset_post()Saves the post for the loaded changeset.
- WP_Customize_Nav_Menus::insert_auto_draft_post()Adds a new `auto-draft` post.
- WP_Embed::shortcode()The do_shortcode() callback function.
- WP_Navigation_Fallback::create_classic_menu_fallback()Creates a Navigation Menu post from a Classic Menu.
- WP_Navigation_Fallback::create_default_fallback()Creates a default Navigation Block Menu fallback.
- WP_REST_Posts_Controller::create_item()Creates a single post.
- WP_REST_Templates_Controller::create_item()Creates a single template.
- WP_REST_Templates_Controller::update_item()Updates a single template.
- WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles()Returns the custom post type that contains the user's origin config for the active theme or an empty array if none are found.
- _wp_put_post_revision()Inserts post data into the posts table as a post revision.
- block_core_navigation_maybe_use_classic_menu_fallback()If there's a classic menu then use it as a fallback.
- get_default_post_to_edit()Returns default post information to use when populating the "Write Post" form.
Show all 21
- wp_create_user_request()Creates and logs a user request to perform a specific action.
- wp_insert_attachment()Inserts an attachment.
- wp_update_custom_css_post()Updates the `custom_css` post for a given theme.
- wp_update_nav_menu_item()Saves the properties of a menu item or create a new one.
- wp_update_post()Updates a post with new post data.
- wp_write_post()Creates a new post from the "Write Post" form using `$_POST` information.
- wp_xmlrpc_server::_insert_post()Helper method for wp_newPost() and wp_editPost(), containing shared logic.
- wp_xmlrpc_server::blogger_newPost()Creates a new post.
- wp_xmlrpc_server::mw_newPost()Creates a new post.
Source
function wp_insert_post( $postarr, $wp_error = false, $fire_after_hooks = true ) { global $wpdb; // Capture original pre-sanitized array for passing into filters. $unsanitized_postarr = $postarr; $user_id = get_current_user_id(); $defaults = array( 'post_author' => $user_id, 'post_content' => '', 'post_content_filtered' => '', 'post_title' => '', 'post_excerpt' => '', 'post_status' => 'draft', 'post_type' => 'post', 'comment_status' => '', 'ping_status' => '', 'post_password' => '', 'to_ping' => '', 'pinged' => '', 'post_parent' => 0, 'menu_order' => 0, 'guid' => '', 'import_id' => 0, 'context' => '', 'post_date' => '', 'post_date_gmt' => '', ); $postarr = wp_parse_args( $postarr, $defaults ); unset( $postarr['filter'] ); $postarr = sanitize_post( $postarr, 'db' ); // Are we updating or creating? $post_id = 0; $update = false; $guid = $postarr['guid']; if ( ! empty( $postarr['ID'] ) ) { $update = true; // Get the post ID and GUID. $post_id = $postarr['ID']; $post_before = get_post( $post_id ); if ( is_null( $post_before ) ) { if ( $wp_error ) { return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) ); } return 0; } $guid = get_post_field( 'guid', $post_id ); $previous_status = get_post_field( 'post_status', $post_id ); } else { $previous_status = 'new'; $post_before = null; } $post_type = empty( $postarr['post_type'] ) ? 'post' : $postarr['post_type']; $post_title = $postarr['post_title']; $post_content = $postarr['post_content']; $post_excerpt = $postarr['post_excerpt']; if ( isset( $postarr['post_name'] ) ) { $post_name = $postarr['post_name']; } elseif ( $update ) { // For an update, don't modify the post_name if it wasn't supplied as an argument. $post_name = $post_before->post_name; } $maybe_empty = 'attachment' !== $post_type && ! $post_content && ! $post_title && ! $post_excerpt && post_type_supports( $post_type, 'editor' ) && post_type_supports( $post_type, 'title' ) && post_type_supports( $post_type, 'excerpt' );History
Introduced in 1.0.0. Unchanged from 6.7.7 through 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
$fire_after_hooks parameter.from the docblock$postarr to add post meta data.from the docblock$wp_error parameter to allow a WP_Error to be returned on failure.from the docblockAbout this page
- Parsed data
- Generated from the wordpress-develop 6.8.8 tag, from
src/wp-includes/post.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it. - Corrections
- Something wrong on this page? Report it and it gets fixed in the next regeneration.