Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I've written a plugin which retrieves an xml file, parses and creates a series of short posts from the content.

Although each post is very short (sometimes just a single sentence, never more than a few sentences), there are around 1000 posts to create from the file.

Using wp_insert_post takes enough time for this job to timeout giving a 500 status.

I also encounter similar problems when deactivating the plugin and trying to move the same content.

Are there any quicker ways of populating (or removing) posts?

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

You can access the database with an INSERT statement and add multiple rows at once.

Something like this pseudo-code:

INSERT INTO $wpdb->posts (
`post_author`, 
`post_date`, 
`post_date_gmt`, 
`post_content`, 
`post_title`, 
`post_status`, 
`post_name`, 
`post_modified`, 
`guid`, 
`post_type`, 
`post_mime_type`
) 
VALUES
    ( $user_id, $current_date,$current_date_gmt, $content1 ),
    ( $user_id, $current_date,$current_date_gmt, $content2 ),
    ( $user_id, $current_date,$current_date_gmt, $content3 )
;

Make sure to fill all the values that are set to NOT NULL and have no default value in the post table schema.
From wp-admin/includes/schema.php:

CREATE TABLE $wpdb->posts (
  ID bigint(20) unsigned NOT NULL auto_increment,
  post_author bigint(20) unsigned NOT NULL default '0',
  post_date datetime NOT NULL default '0000-00-00 00:00:00',
  post_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
  post_content longtext NOT NULL,
  post_title text NOT NULL,
  post_excerpt text NOT NULL,
  post_status varchar(20) NOT NULL default 'publish',
  comment_status varchar(20) NOT NULL default 'open',
  ping_status varchar(20) NOT NULL default 'open',
  post_password varchar(20) NOT NULL default '',
  post_name varchar(200) NOT NULL default '',
  to_ping text NOT NULL,
  pinged text NOT NULL,
  post_modified datetime NOT NULL default '0000-00-00 00:00:00',
  post_modified_gmt datetime NOT NULL default '0000-00-00 00:00:00',
  post_content_filtered longtext NOT NULL,
  post_parent bigint(20) unsigned NOT NULL default '0',
  guid varchar(255) NOT NULL default '',
  menu_order int(11) NOT NULL default '0',
  post_type varchar(20) NOT NULL default 'post',
  post_mime_type varchar(100) NOT NULL default '',
  comment_count bigint(20) NOT NULL default '0',
  PRIMARY KEY  (ID),
  KEY post_name (post_name),
  KEY type_status_date (post_type,post_status,post_date,ID),
  KEY post_parent (post_parent),
  KEY post_author (post_author)
) $charset_collate;\n";

Also, regular posts need a default category. Not sure what happens if you omit that.

share|improve this answer
    
Thanks - any gotchas I should look out for with this approach? (i.e. what is it that wp_insert_post is protecting me from mucking up?) –  Owen Stephens Dec 11 '12 at 10:38
    
@OwenStephens See my update. –  toscho Dec 11 '12 at 11:10
    
It's just $wpdb->posts, not $wpdb->prefix.posts. +1 anyway. –  kaiser Dec 11 '12 at 11:16
    
Another thing: Normally there's a callback incrementing the count for posts for a tag or a category. You'll have to also add that manually, when looping through. –  kaiser Dec 11 '12 at 11:17
add comment

Not using the API might save you a minute now but cost you hours later. I have done similiar things and run into timeouts but not 500, you should realy check the php and appache logs first to try and find the cuase.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.