Вы находитесь на странице: 1из 24

Browse: Home / Reference / Functions / wp_insert_post()

wp_insert_post( array $postarr, bool $wp_error = false )


Insert or update a post.

CONTENTS
 Description
o See also
o Parameters
o Return
o Source
o Changelog
 More Information
o Usage
o Notes
o Categories
o Security
 Related
o Uses
o Used By
 User Contributed Notes

Description #Description
If the $postarr parameter has ‘ID’ set to a value, then post will be updated.

You can set the post date manually, by setting the values for ‘post_date’ and ‘post_date_gmt’
keys. You can close the comments or open the comments by setting the value for
‘comment_status’ key.

See also #See also

 sanitize_post()

Top ↑

Parameters #Parameters

$postarr
(array) (Required) An array of elements that make up a post to update or insert.
 'ID'
(int) The post ID. If equal to something other than 0, the post with that ID will be
updated. Default 0.
 'post_author'
(int) The ID of the user who added the post. Default is the current user ID.
 'post_date'
(string) The date of the post. Default is the current time.
 'post_date_gmt'
(string) The date of the post in the GMT timezone. Default is the value
of $post_date.
 'post_content'
(mixed) The post content. Default empty.
 'post_content_filtered'
(string) The filtered post content. Default empty.
 'post_title'
(string) The post title. Default empty.
 'post_excerpt'
(string) The post excerpt. Default empty.
 'post_status'
(string) The post status. Default 'draft'.
 'post_type'
(string) The post type. Default 'post'.
 'comment_status'
(string) Whether the post can accept comments. Accepts 'open' or 'closed'. Default
is the value of 'default_comment_status' option.
 'ping_status'
(string) Whether the post can accept pings. Accepts 'open' or 'closed'. Default is
the value of 'default_ping_status' option.
 'post_password'
(string) The password to access the post. Default empty.
 'post_name'
(string) The post name. Default is the sanitized post title when creating a new post.
 'to_ping'
(string) Space or carriage return-separated list of URLs to ping. Default empty.
 'pinged'
(string) Space or carriage return-separated list of URLs that have been pinged.
Default empty.
 'post_modified'
(string) The date when the post was last modified. Default is the current time.
 'post_modified_gmt'
(string) The date when the post was last modified in the GMT timezone. Default is
the current time.
 'post_parent'
(int) Set this for the post it belongs to, if any. Default 0.
 'menu_order'
(int) The order the post should be displayed in. Default 0.
 'post_mime_type'
(string) The mime type of the post. Default empty.
 'guid'
(string) Global Unique ID for referencing the post. Default empty.
 'post_category'
(array) Array of category names, slugs, or IDs. Defaults to value of the
'default_category' option.
 'tags_input'
(array) Array of tag names, slugs, or IDs. Default empty.
 'tax_input'
(array) Array of taxonomy terms keyed by their taxonomy name. Default empty.
 'meta_input'
(array) Array of post meta values keyed by their post meta key. Default empty.
$wp_error
(bool) (Optional) Whether to return a WP_Error on failure.
Default value: false

Top ↑

Return #Return

(int|WP_Error) The post ID on success. The value 0 or WP_Error on failure.

Top ↑

Source #Source

File: wp-includes/post.php

3044 function wp_insert_post( $postarr, $wp_error = false ) {


3045 global $wpdb;
3046
$user_id = get_current_user_id();
3047
3048 $defaults = array(
3049 'post_author' => $user_id,
3050 'post_content' => '',
3051 'post_content_filtered' => '',
3052 'post_title' => '',
'post_excerpt' => '',
3053 'post_status' => 'draft',
3054 'post_type' => 'post',
3055 'comment_status' => '',
3056 'ping_status' => '',
3057 'post_password' => '',
'to_ping' => '',
3058 'pinged' => '',
3059 'post_parent' => 0,
3060 'menu_order' => 0,
3061 'guid' => '',
'import_id' => 0,
3062 'context' => '',
3063 );
3064
3065 $postarr = wp_parse_args($postarr, $defaults);
3066
3067 unset( $postarr[ 'filter' ] );
3068
3069 $postarr = sanitize_post($postarr, 'db');
3070
// Are we updating or creating?
3071 $post_ID = 0;
3072 $update = false;
3073 $guid = $postarr['guid'];
3074
3075 if ( ! empty( $postarr['ID'] ) ) {
$update = true;
3076
3077 // Get the post ID and GUID.
3078 $post_ID = $postarr['ID'];
3079 $post_before = get_post( $post_ID );
3080 if ( is_null( $post_before ) ) {
3081 if ( $wp_error ) {
return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
3082 }
3083 return 0;
3084 }
3085
3086 $guid = get_post_field( 'guid', $post_ID );
3087 $previous_status = get_post_field('post_status', $post_ID );
} else {
3088 $previous_status = 'new';
3089 }
3090
3091 $post_type = empty( $postarr['post_type'] ) ? 'post' : $postarr['post_type'];
3092
3093 $post_title = $postarr['post_title'];
$post_content = $postarr['post_content'];
3094 $post_excerpt = $postarr['post_excerpt'];
3095 if ( isset( $postarr['post_name'] ) ) {
3096 $post_name = $postarr['post_name'];
3097 } elseif ( $update ) {
3098 // For an update, don't modify the post_name if it wasn't supplied as an
$post_name = $post_before->post_name;
3099 }
3100
3101 $maybe_empty = 'attachment' !== $post_type
3102 && ! $post_content && ! $post_title && ! $post_excerpt
&& post_type_supports( $post_type, 'editor' )
3103 && post_type_supports( $post_type, 'title' )
3104 && post_type_supports( $post_type, 'excerpt' );
3105
3106 /**
3107 * Filters whether the post should be considered "empty".
*
3108 * The post is considered "empty" if both:
3109 * 1. The post type supports the title, editor, and excerpt fields
3110 * 2. The title, editor, and excerpt fields are all empty
3111 *
3112 * Returning a truthy value to the filter will effectively short-circuit
* the new post being inserted, returning 0. If $wp_error is true, a WP_Erro
3113 * will be returned instead.
3114 *
3115 * @since 3.3.0
3116 *
* @param bool $maybe_empty Whether the post should be considered "empty".
3117 * @param array $postarr Array of post data.
3118 */
3119 if ( apply_filters( 'wp_insert_post_empty_content', $maybe_empty, $postarr )
3120 if ( $wp_error ) {
3121 return new WP_Error( 'empty_content', __( 'Content, title, and excerp
} else {
3122 return 0;
3123 }
3124 }
3125
3126 $post_status = empty( $postarr['post_status'] ) ? 'draft' : $postarr['post_st
3127 if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit'
$post_status = 'inherit';
3128 }
3129
3130 if ( ! empty( $postarr['post_category'] ) ) {
3131 // Filter out empty terms.
3132 $post_category = array_filter( $postarr['post_category'] );
}
3133
3134 // Make sure we set a valid category.
3135 if ( empty( $post_category ) || 0 == count( $post_category ) || ! is_array( $p
3136 // 'post' requires at least one category.
3137 if ( 'post' == $post_type && 'auto-draft' != $post_status ) {
3138 $post_category = array( get_option('default_category') );
} else {
3139 $post_category = array();
3140 }
3141 }
3142
3143 // Don't allow contributors to set the post slug for pending review posts.
if ( 'pending' == $post_status && !current_user_can( 'publish_posts' ) ) {
3144 $post_name = '';
3145 }
3146
3147 /*
3148 * Create a valid post name. Drafts and pending posts are allowed to have
* an empty post name.
3149 */
3150 if ( empty($post_name) ) {
3151 if ( !in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) )
3152 $post_name = sanitize_title($post_title);
} else {
3153 $post_name = '';
3154 }
3155 } else {
3156 // On updates, we need to check to see if it's using the old, fixed sani
3157 $check_name = sanitize_title( $post_name, '', 'old-save' );
if ( $update && strtolower( urlencode( $post_name ) ) == $check_name && ge
3158 $post_name = $check_name;
3159 } else { // new post, or slug has changed.
3160 $post_name = sanitize_title($post_name);
3161 }
}
3162
3163 /*
3164 * If the post date is empty (due to having been new or a draft) and status
3165 * is not 'draft' or 'pending', set date to now.
3166 */
3167 if ( empty( $postarr['post_date'] ) || '0000-00-00 00:00:00' == $postarr['pos
if ( empty( $postarr['post_date_gmt'] ) || '0000-00-00 00:00:00' == $post
3168 $post_date = current_time( 'mysql' );
3169 } else {
3170 $post_date = get_date_from_gmt( $postarr['post_date_gmt'] );
3171 }
3172 } else {
$post_date = $postarr['post_date'];
3173 }
3174
3175 // Validate the date.
3176 $mm = substr( $post_date, 5, 2 );
3177 $jj = substr( $post_date, 8, 2 );
$aa = substr( $post_date, 0, 4 );
3178 $valid_date = wp_checkdate( $mm, $jj, $aa, $post_date );
3179 if ( ! $valid_date ) {
3180 if ( $wp_error ) {
3181 return new WP_Error( 'invalid_date', __( 'Invalid date.' ) );
3182 } else {
return 0;
3183 }
3184 }
3185
3186 if ( empty( $postarr['post_date_gmt'] ) || '0000-00-00 00:00:00' == $postarr[
3187 if ( ! in_array( $post_status, array( 'draft', 'pending', 'auto-draft' )
$post_date_gmt = get_gmt_from_date( $post_date );
3188 } else {
3189 $post_date_gmt = '0000-00-00 00:00:00';
3190 }
3191 } else {
3192 $post_date_gmt = $postarr['post_date_gmt'];
}
3193
3194 if ( $update || '0000-00-00 00:00:00' == $post_date ) {
3195 $post_modified = current_time( 'mysql' );
3196 $post_modified_gmt = current_time( 'mysql', 1 );
3197 } else {
3198 $post_modified = $post_date;
3199 $post_modified_gmt = $post_date_gmt;
3200 }
3201
if ( 'attachment' !== $post_type ) {
3202 if ( 'publish' == $post_status ) {
3203 $now = gmdate('Y-m-d H:i:59');
3204 if ( mysql2date('U', $post_date_gmt, false) > mysql2date('U', $now, f
3205 $post_status = 'future';
}
3206 } elseif ( 'future' == $post_status ) {
3207 $now = gmdate('Y-m-d H:i:59');
3208 if ( mysql2date('U', $post_date_gmt, false) <= mysql2date('U', $now,
3209 $post_status = 'publish';
3210 }
}
3211 }
3212
3213 // Comment status.
3214 if ( empty( $postarr['comment_status'] ) ) {
3215 if ( $update ) {
$comment_status = 'closed';
3216 } else {
3217 $comment_status = get_default_comment_status( $post_type );
3218 }
3219 } else {
3220 $comment_status = $postarr['comment_status'];
}
3221
3222 // These variables are needed by compact() later.
3223 $post_content_filtered = $postarr['post_content_filtered'];
3224 $post_author = isset( $postarr['post_author'] ) ? $postarr['post_author'] : $
3225 $ping_status = empty( $postarr['ping_status'] ) ? get_default_comment_status(
$to_ping = isset( $postarr['to_ping'] ) ? sanitize_trackback_urls( $postarr['
3226
$pinged = isset( $postarr['pinged'] ) ? $postarr['pinged'] : '';
3227 $import_id = isset( $postarr['import_id'] ) ? $postarr['import_id'] : 0;
3228
3229 /*
3230 * The 'wp_insert_post_parent' filter expects all variables to be present.
3231 * Previously, these variables would have already been extracted
*/
3232 if ( isset( $postarr['menu_order'] ) ) {
3233 $menu_order = (int) $postarr['menu_order'];
3234 } else {
3235 $menu_order = 0;
3236 }
3237
3238 $post_password = isset( $postarr['post_password'] ) ? $postarr['post_password
if ( 'private' == $post_status ) {
3239 $post_password = '';
3240 }
3241
3242 if ( isset( $postarr['post_parent'] ) ) {
3243 $post_parent = (int) $postarr['post_parent'];
} else {
3244 $post_parent = 0;
3245 }
3246
3247 /**
3248 * Filters the post parent -- used to check for and prevent hierarchy loops.
3249 *
* @since 3.1.0
3250 *
3251 * @param int $post_parent Post parent ID.
3252 * @param int $post_ID Post ID.
3253 * @param array $new_postarr Array of parsed post data.
* @param array $postarr Array of sanitized, but otherwise unmodified po
3254 */
3255 $post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID
3256
3257 /*
3258 * If the post is being untrashed and it has a desired slug stored in post m
3259 * reassign it.
*/
3260 if ( 'trash' === $previous_status && 'trash' !== $post_status ) {
3261 $desired_post_slug = get_post_meta( $post_ID, '_wp_desired_post_slug', tr
3262 if ( $desired_post_slug ) {
3263 delete_post_meta( $post_ID, '_wp_desired_post_slug' );
3264 $post_name = $desired_post_slug;
}
3265 }
3266
3267 // If a trashed post has the desired slug, change it and let this post have
3268 if ( 'trash' !== $post_status && $post_name ) {
3269 wp_add_trashed_suffix_to_post_name_for_trashed_posts( $post_name, $post_
}
3270
3271 // When trashing an existing post, change its slug to allow non-trashed post
3272 if ( 'trash' === $post_status && 'trash' !== $previous_status && 'new' !== $pre
3273 $post_name = wp_add_trashed_suffix_to_post_name_for_post( $post_ID );
3274 }
3275
3276 $post_name = wp_unique_post_slug( $post_name, $post_ID, $post_status, $post_t
3277
// Don't unslash.
3278 $post_mime_type = isset( $postarr['post_mime_type'] ) ? $postarr['post_mime_t
3279
3280 // Expected_slashed (everything!).
3281 $data = compact( 'post_author', 'post_date', 'post_date_gmt', 'post_content',
3282 'comment_status', 'ping_status', 'post_password', 'post_name', 'to_ping', 'pinge
'post_mime_type', 'guid' );
3283
3284 $emoji_fields = array( 'post_title', 'post_content', 'post_excerpt' );
3285
3286 foreach ( $emoji_fields as $emoji_field ) {
3287 if ( isset( $data[ $emoji_field ] ) ) {
3288 $charset = $wpdb->get_col_charset( $wpdb->posts, $emoji_field );
if ( 'utf8' === $charset ) {
3289 $data[ $emoji_field ] = wp_encode_emoji( $data[ $emoji_field ] );
3290 }
3291 }
3292 }
3293
3294 if ( 'attachment' === $post_type ) {
/**
3295 * Filters attachment post data before it is updated in or added to the
3296 *
3297 * @since 3.9.0
3298 *
* @param array $data An array of sanitized attachment post data.
3299 * @param array $postarr An array of unsanitized attachment post data.
3300 */
3301 $data = apply_filters( 'wp_insert_attachment_data', $data, $postarr );
3302 } else {
3303 /**
* Filters slashed post data just before it is inserted into the databas
3304 *
3305 * @since 2.7.0
3306 *
3307 * @param array $data An array of slashed post data.
3308 * @param array $postarr An array of sanitized, but otherwise unmodified
*/
3309 $data = apply_filters( 'wp_insert_post_data', $data, $postarr );
3310 }
3311 $data = wp_unslash( $data );
3312 $where = array( 'ID' => $post_ID );
3313
if ( $update ) {
3314 /**
3315 * Fires immediately before an existing post is updated in the database.
3316 *
3317 * @since 2.5.0
3318 *
* @param int $post_ID Post ID.
3319 * @param array $data Array of unslashed post data.
3320 */
3321 do_action( 'pre_post_update', $post_ID, $data );
3322 if ( false === $wpdb->update( $wpdb->posts, $data, $where ) ) {
if ( $wp_error ) {
3323 return new WP_Error('db_update_error', __('Could not update post
3324 } else {
3325 return 0;
3326 }
3327 }
} else {
3328 // If there is a suggested ID, use it if not already present.
3329 if ( ! empty( $import_id ) ) {
3330 $import_id = (int) $import_id;
3331 if ( ! $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->posts WH
$data['ID'] = $import_id;
3332 }
3333 }
3334 if ( false === $wpdb->insert( $wpdb->posts, $data ) ) {
3335 if ( $wp_error ) {
3336 return new WP_Error('db_insert_error', __('Could not insert post
} else {
3337 return 0;
3338 }
3339 }
3340 $post_ID = (int) $wpdb->insert_id;
3341
// Use the newly generated $post_ID.
3342 $where = array( 'ID' => $post_ID );
3343 }
3344
3345 if ( empty( $data['post_name'] ) && ! in_array( $data['post_status'], array(
3346 $data['post_name'] = wp_unique_post_slug( sanitize_title( $data['post_ti
3347 $wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ),
clean_post_cache( $post_ID );
3348 }
3349
3350 if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
3351 wp_set_post_categories( $post_ID, $post_category );
3352 }
3353
3354 if ( isset( $postarr['tags_input'] ) && is_object_in_taxonomy( $post_type, 'p
wp_set_post_tags( $post_ID, $postarr['tags_input'] );
3355 }
3356
3357 // New-style support for all custom taxonomies.
3358 if ( ! empty( $postarr['tax_input'] ) ) {
3359 foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
$taxonomy_obj = get_taxonomy($taxonomy);
3360 if ( ! $taxonomy_obj ) {
3361 /* translators: %s: taxonomy name */
3362 _doing_it_wrong( __FUNCTION__, sprintf( __( 'Invalid taxonomy: %
3363 continue;
3364 }
3365
// array = hierarchical, string = non-hierarchical.
3366 if ( is_array( $tags ) ) {
3367 $tags = array_filter($tags);
3368 }
3369 if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
wp_set_post_terms( $post_ID, $tags, $taxonomy );
3370
3371 }
3372 }
}
3373
3374 if ( ! empty( $postarr['meta_input'] ) ) {
3375 foreach ( $postarr['meta_input'] as $field => $value ) {
3376 update_post_meta( $post_ID, $field, $value );
3377 }
}
3378
3379 $current_guid = get_post_field( 'guid', $post_ID );
3380
3381 // Set GUID.
3382 if ( ! $update && '' == $current_guid ) {
3383 $wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post_ID ) )
3384 }
3385
if ( 'attachment' === $postarr['post_type'] ) {
3386 if ( ! empty( $postarr['file'] ) ) {
3387 update_attached_file( $post_ID, $postarr['file'] );
3388 }
3389
3390 if ( ! empty( $postarr['context'] ) ) {
add_post_meta( $post_ID, '_wp_attachment_context', $postarr['context
3391 }
3392 }
3393
3394 // Set or remove featured image.
3395 if ( isset( $postarr['_thumbnail_id'] ) ) {
3396 $thumbnail_support = current_theme_supports( 'post-thumbnails', $post_typ
if ( ! $thumbnail_support && 'attachment' === $post_type && $post_mime_typ
3397 if ( wp_attachment_is( 'audio', $post_ID ) ) {
3398 $thumbnail_support = post_type_supports( 'attachment:audio', 'thu
3399 } elseif ( wp_attachment_is( 'video', $post_ID ) ) {
3400 $thumbnail_support = post_type_supports( 'attachment:video', 'thu
3401 }
}
3402
3403 if ( $thumbnail_support ) {
3404 $thumbnail_id = intval( $postarr['_thumbnail_id'] );
3405 if ( -1 === $thumbnail_id ) {
3406 delete_post_thumbnail( $post_ID );
} else {
3407 set_post_thumbnail( $post_ID, $thumbnail_id );
3408 }
3409 }
3410 }
3411
3412 clean_post_cache( $post_ID );
3413
$post = get_post( $post_ID );
3414
3415 if ( ! empty( $postarr['page_template'] ) ) {
3416 $post->page_template = $postarr['page_template'];
3417 $page_templates = wp_get_theme()->get_page_templates( $post );
if ( 'default' != $postarr['page_template'] && ! isset( $page_templates[
3418 if ( $wp_error ) {
3419 return new WP_Error( 'invalid_page_template', __( 'Invalid page t
3420 }
3421 update_post_meta( $post_ID, '_wp_page_template', 'default' );
} else {
3422 update_post_meta( $post_ID, '_wp_page_template', $postarr['page_temp
3423 }
3424 }
3425
3426 if ( 'attachment' !== $postarr['post_type'] ) {
3427 wp_transition_post_status( $data['post_status'], $previous_status, $post
} else {
3428 if ( $update ) {
3429 /**
3430 * Fires once an existing attachment has been updated.
3431 *
* @since 2.0.0
3432 *
3433 * @param int $post_ID Attachment ID.
3434 */
3435 do_action( 'edit_attachment', $post_ID );
3436 $post_after = get_post( $post_ID );
3437
/**
3438 * Fires once an existing attachment has been updated.
3439 *
3440 * @since 4.4.0
3441 *
3442 * @param int $post_ID Post ID.
* @param WP_Post $post_after Post object following the update.
3443 * @param WP_Post $post_before Post object before the update.
3444 */
3445 do_action( 'attachment_updated', $post_ID, $post_after, $post_before
3446 } else {
3447
/**
3448 * Fires once an attachment has been added.
3449 *
3450 * @since 2.0.0
3451 *
3452 * @param int $post_ID Attachment ID.
*/
3453 do_action( 'add_attachment', $post_ID );
3454 }
3455
3456 return $post_ID;
3457 }
3458
if ( $update ) {
3459 /**
3460 * Fires once an existing post has been updated.
3461 *
3462 * @since 1.2.0
*
3463 * @param int $post_ID Post ID.
3464 * @param WP_Post $post Post object.
3465 */
3466 do_action( 'edit_post', $post_ID, $post );
$post_after = get_post($post_ID);
3467
3468 /**
3469 * Fires once an existing post has been updated.
3470 *
3471 * @since 3.0.0
3472 *
* @param int $post_ID Post ID.
3473 * @param WP_Post $post_after Post object following the update.
3474 * @param WP_Post $post_before Post object before the update.
3475 */
3476 do_action( 'post_updated', $post_ID, $post_after, $post_before);
}
3477
3478 /**
3479 * Fires once a post has been saved.
3480 *
3481 * The dynamic portion of the hook name, `$post->post_type`, refers to
3482 * the post type slug.
*
3483 * @since 3.7.0
3484 *
3485 * @param int $post_ID Post ID.
3486 * @param WP_Post $post Post object.
3487 * @param bool $update Whether this is an existing post being updated or
*/
3488 do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );
3489
3490 /**
3491 * Fires once a post has been saved.
3492 *
* @since 1.5.0
3493 *
3494 * @param int $post_ID Post ID.
3495 * @param WP_Post $post Post object.
3496 * @param bool $update Whether this is an existing post being updated or
3497 */
do_action( 'save_post', $post_ID, $post, $update );
3498
3499 /**
3500 * Fires once a post has been saved.
3501 *
3502 * @since 2.0.0
*
3503 * @param int $post_ID Post ID.
3504 * @param WP_Post $post Post object.
3505 * @param bool $update Whether this is an existing post being updated or
3506 */
3507 do_action( 'wp_insert_post', $post_ID, $post, $update );
3508
return $post_ID;
3509 }
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
Expand full source code View on Trac

Top ↑

Changelog #Changelog

Version Description

4.4.0 A 'meta_input' array can now be passed to $postarr to add post meta data.

4.2.0 Support was added for encoding emoji in the post title, content, and excerpt.

1.0.0 Introduced.

Changelog

Top ↑

More Information #More Information


Top ↑

Usage #Usage

1 wp_insert_post( $post, $wp_error );

Top ↑

Notes #Notes

 post_title and post_content are required


 post_status: If providing a post_status of ‘future’ you must specify the post_date in
order for WordPress to know when to publish your post. See also Post Status Transitions.
 post_category: Equivalent to calling wp_set_post_categories().
 tags_input: Equivalent to calling wp_set_post_tags().
 tax_input: Equivalent to calling wp_set_post_terms() for each custom taxonomy in the
array. If the current user doesn’t have the capability to work with a taxonomy, then you
must use wp_set_object_terms() instead.
 page_template: If post_type is ‘page’, will attempt to set the page template. On failure,
the function will return either a WP_Error or 0, and stop before the final actions are
called. If the post_type is not ‘page’, the parameter is ignored. You can set the page
template for a non-page by calling update_post_meta() with a key of
‘_wp_page_template’.
Top ↑

Categories #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.

See also: wp_set_post_terms()


Top ↑

Security #Security

wp_insert_post() passes data through sanitize_post(), which itself handles all necessary
sanitization and validation (kses, etc.).
As such, you don’t need to worry about that.

You may wish, however, to remove HTML, JavaScript, and PHP tags from the post_title and any
other fields. Surprisingly, WordPress does not do this automatically. This can be easily done by
using the wp_strip_all_tags() function and is especially useful when building front-end post
submission forms.

1 // Create post object


2 $my_post = array(
3 'post_title' => wp_strip_all_tags( $_POST['post_title'] ),
4 'post_content' => $_POST['post_content'],
5 'post_status' => 'publish',
6 'post_author' => 1,
7 'post_category' => array( 8,39 )
8 );
9
10 // Insert the post into the database
wp_insert_post( $my_post );
11

Top ↑
Related #Related
Top ↑

Uses #Uses

 wp-includes/post.php: wp_add_trashed_suffix_to_post_name_for_trashed_posts()
 wp-includes/post.php: wp_add_trashed_suffix_to_post_name_for_post()
 wp-includes/post.php: attachment_updated
 wp-includes/comment.php: get_default_comment_status()
 wp-includes/post.php: add_attachment
Show 58 more uses

Top ↑

Used By #Used By

 wp-includes/class-wp-customize-
manager.php: WP_Customize_Manager::save_changeset_post()
 wp-includes/theme.php: wp_update_custom_css_post()
 wp-includes/rest-api/endpoints/class-wp-rest-attachments-
controller.php:WP_REST_Attachments_Controller::create_item()
 wp-includes/rest-api/endpoints/class-wp-rest-posts-
controller.php: WP_REST_Posts_Controller::create_item()
 wp-includes/class-wp-customize-nav-
menus.php: WP_Customize_Nav_Menus::insert_auto_draft_post()
Show 10 more used by

Top ↑

User Contributed Notes #User Contributed Notes


1. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:8You must log in to vote on the helpfulness of this note

Contributed by truongwp — 2 years ago

Insert post with custom taxonomy and post meta data (since 4.4.0):
1
$hierarchical_tax = array( 13, 10 ); // Array of tax ids.
2 $non_hierarchical_tax = 'tax name 1, tax name 2'; // Can use array of ids or string
3
4 $post_arr = array(
5 'post_title' => 'Test post',
6 'post_content' => 'Test post content',
7 'post_status' => 'publish',
8 'post_author' => get_current_user_id(),
9 'tax_input' => array(
10 'hierarchical_tax' => $hierarchical_tax,
11 'non_hierarchical_tax' => $non_hierarchical_tax,
12 ),
13 'meta_input' => array(
14 'test_meta_key' => 'value of test_meta_key',
),
15 );
16

Expand full source code

Log in to add feedback

2. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:7You must log in to vote on the helpfulness of this note

Contributed by Codex — 3 years ago

Inserting a Post
Before calling wp_insert_post() it is necessary to create an array to pass the necessary
elements that make up a post. The wp_insert_post() will fill out a default list of these but the
user is required to provide the title and content otherwise the database write will fail.
The next example shows the post title, content, status, author, and post categories being set. You
can add further key-value pairs, making sure the keys match the names of the columns in
the wp_posts table in the database.

1 // Gather post data.


2 $my_post = array(
3 'post_title' => 'My post',
4 'post_content' => 'This is my post.',
5 'post_status' => 'publish',
6 'post_author' => 1,
7 'post_category' => array( 8,39 )
8 );
9
10 // Insert the post into the database.
11 wp_insert_post( $my_post );

You can also get the new post ID after inserting a new post:

1 $post_id = wp_insert_post( $post, $wp_error );

Log in to add feedback

3. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:6You must log in to vote on the helpfulness of this note

Contributed by NateWr — 3 years ago

By default, wp_insert_post will not insert an empty post. This can cause unexpected problems
if you’re passing an ID and expecting it to fall back to wp_update_post. For instance, the
following will not work:

1 wp_insert_post( array( 'ID' => 2, 'post_parent' => 1 ) );

You will need to call wp_update_post directly.

1 wp_update_post( array( 'ID' => 2, 'post_parent' => 1 ) );

Log in to add feedback

4. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:3You must log in to vote on the helpfulness of this note

Contributed by Kiera Howe — 1 year ago

‘tax_input’ in the arguments only works on wp_insert_post if the function is being called by a
user with “assign_terms” access

https://core.trac.wordpress.org/browser/tags/4.7/src/wp-includes/post.php#L3352
Log in to add feedback

5. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:2You must log in to vote on the helpfulness of this note

Contributed by Compute — 10 months ago

When saving data containing slashes remember to add extra slashes due
to wp_insert_post unslashing these values.

1
$regex = '(\b16-\d{3}\b)';
2 $post_data = array(
3 'post_title' => 'Test regex',
4 'post_content' => $regex,
5 'post_type' => 'post',
);
6 $post_id = wp_insert_post( $post_data );
7

Will store (b16-d{3}b). To fix this use wp_slash():

1
$regex = '(\b16-\d{3}\b)';
2 $post_data = array(
3 'post_title' => 'Test regex',
4 'post_content' => wp_slash( $regex ),
5 'post_type' => 'post',
);
6 $post_id = wp_insert_post( $post_data );
7

Log in to add feedback

6. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:1You must log in to vote on the helpfulness of this note

Contributed by Aurovrata Venet — 1 year ago

Its important that you validate your post ID before you use by checking if the returned values is
not a WP_error,
1
2 $args = array(
3 'post_type' => 'my_custom_post',
/*other default parameters you want to set*/
4 );
5 $post_id = wp_insert_post($args);
6 if(!is_wp_error($post_id)){
7 //the post is valid
}else{
8 //there was an error in the post insertion,
9 echo $post_id->get_error_message();
10 }
11

Log in to add feedback

7. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:1You must log in to vote on the helpfulness of this note

Contributed by Pablo Pacheco — 7 months ago

As @Kiera Howe brilliantly noticed, ‘tax_input’ requires ‘assign_terms’ access.


Depending on the case it can make its use impracticable.
A quick solution could be replacing it by:

1 wp_set_object_terms( $post_id, array( $term_id1, $term_id2 ), 'tax_slug' );

Reference:
https://ryansechrest.com/2012/07/wordpress-taxonomy-terms-dont-insert-when-cron-job-
executes-wp_insert_post/

Log in to add feedback

8. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:0You must log in to vote on the helpfulness of this note

Contributed by daniyalahmedk — 2 years ago

Create a post for custom post type :


1 $id = wp_insert_post(array('post_title'=>'random', 'post_type'=>'custom_post', 'post

Log in to add feedback

9. Skip to note content

You must log in to vote on the helpfulness of this noteVote results for this
note:0You must log in to vote on the helpfulness of this note

Contributed by Oscar Abad Folgueira — 6 months ago

This snippet creates a post with code checking if the post already exists before creating it.

1 function create_wordpress_post_with_code() {
2
// Set the post ID to -1. This sets to no action at moment
3 $post_id = -1;
4
5 // Set the Author, Slug, title and content of the new post
6 $author_id = 1;
7 $slug = 'wordpress-post-created-with-code';
$title = 'WordPress post created whith code';
8
$content = 'This is the content of the post that we are creating right now
9 More text: I motsetning til hva mange tror, er ikke Lorem Ipsu
10 Dets røtter springer helt tilbake til et stykke klassisk latin
11 hvilket gjør det over 2000 år gammelt. Richard McClintock - pr
12 College i Virginia, USA - slo opp flere av de mer obskure lati
fra en del av Lorem Ipsum, og fant dets utvilsomme opprinnelse
13 av disse ordene i klassisk litteratur. Lorem Ipsum kommer fra
14 "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil)
15 Boken er en avhandling om teorier rundt etikk, og var veldig po
16 linjen av Lorem Ipsum, "Lorem Ipsum dolor sit amet...", er hen
17 // Cheks if doen't exists a post with slug "wordpress-post-created-with-co
if( !post_exists_by_slug( $slug ) ) {
18 // Set the post ID
19 $post_id = wp_insert_post(
20 array(
21 'comment_status' => 'closed',
22 'ping_status' => 'closed',
23 'post_author' => $author_id,
24 'post_name' => $slug,
25 'post_title' => $title,
26 'post_content' => $content,
27 'post_status' => 'publish',
28 'post_type' => 'post'
29 )
30 );
} else {
31
32 // Set pos_id to -2 becouse there is a post with this slug.
33 $post_id = -2;
34
35 } // end if
36
37 } // end oaf_create_post_with_code
38 add_filter( 'after_setup_theme', 'create_wordpress_post_with_code' );
/**
39 * post_exists_by_slug.
40 *
41 * @return mixed boolean false if no post exists; post ID otherwise.
42 */
function post_exists_by_slug( $post_slug ) {
43 $args_posts = array(
44
'post_type' => 'post',
45
'post_status' => 'any',
46
'name' => $post_slug,
47 'posts_per_page' => 1,
48 );
49 $loop_posts = new WP_Query( $args_posts );
50 if ( ! $loop_posts->have_posts() ) {
return false;
51 } else {
52 $loop_posts->the_post();
53 return $loop_posts->post->ID;
54 }
55 }
56
57
58
59
60
61
62
63

Expand full source code

Log in to add feedback

Вам также может понравиться