In a recent project, a requirement of the WordPress site I was building was to automatically create child posts when adding a post of a certain type. It turns out that this is fairly easy using the wp_insert_post function, but there are a number of factors to take into consideration (not least not creating a new child-post on every page update/revision, etc).
In this particular case, I was using a custom post type for the parent post, because I needed a significant number of custom fields (easily achieved using the excellent Advanced Custom Fields plugin), but the same outcome could easily be done with the standard post type.
In this example, I’m creating two new post types ‘book’ and ‘bookdetail’. Both types are pretty standard – the only slight difference in the project there was a requirement that the child-posts should not be editable or to appear in navigation menus (public, or dashboard), so the lines:
'show_ui' => false, 'show_in_nav_menus' => false,
will hide the posts from the admin interface and from menus; setting to ‘true’ will show them. I also changed the permissions on the type so that certain roles did not have permissions to do anything with these posts other than view them, but I’ll cover how to do that in a separate post.
The following code (when added to your theme’s functions.php file) will create the new post types:
function create_post_type() { register_post_type('book', array( 'labels' => array( 'name' => __('Books'), 'singular_name' => __('Book'), 'add_new' => __('Add book'), 'all_items' => __('All books'), 'add_new_item' => __('Add book'), 'edit_item' => __('Edit book'), 'new_item' => __('New book'), 'view_item' => __('View book'), 'search_items' => __('Search books'), 'not_found' => __('No book found'), 'not_found_in_trash' => __('No book found in trash'), 'parent_item_colon' => __('Parent book') ), 'supports' => array( 'title', 'editor', 'author' // amend options as required ), 'show_ui' => true, 'taxonomies' => array( 'category' ), // add default post categories and tags 'public' => true, 'has_archive' => true, 'rewrite' => array( 'slug' => 'book', 'with_front' => true ), 'menu_position' => 2, 'hierarchical' => true, //'capability_type' => 'book', 'map_meta_cap' => true )); register_post_type('bookdetail', array( 'labels' => array( 'name' => __('Book detail'), 'singular_name' => __('Book detail'), 'add_new' => __('Add book detail'), 'all_items' => __('All book details'), 'add_new_item' => __('Add book detail'), 'edit_item' => __('Edit book detail'), 'new_item' => __('New book detail'), 'view_item' => __('View book detail'), 'search_items' => __('Search book details'), 'not_found' => __('No book found'), 'not_found_in_trash' => __('No book detail found in trash'), 'parent_item_colon' => __('Parent book') ), 'supports' => array( 'title', 'editor', 'author', 'revisions' ), 'show_ui' => false, 'show_in_nav_menus' => false, 'taxonomies' => array( 'category' ), 'public' => true, 'has_archive' => true, 'menu_position' => 2 )); } add_action('init', 'create_post_type');
So now we want to add an action to fire when you save a book parent post, creating the child-post. This function initially checks to make sure that this is not an auto-save – if so, it exits without making any changes. Otherwise, a few further checks are then carried out, making sure you’re saving a ‘book’, that it’s not a revision, draft, or in the trash, or that there are no other children already created. If all the logic is satisfied, then a new child-post is added.
function add_book_children($post_id) { if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) // don't create child on autosave return; if (!wp_is_post_revision($post_id) // don't create child for various posts states && 'book' == get_post_type($post_id) && 'auto-draft' != get_post_status($post_id) && 'trash' != get_post_status($post_id)) {</pre> <pre> $book = get_post($post_id); $parent_title = get_the_title($post_id); if (0 == $book->post_parent) { $children =& get_children(array( 'post_parent' => $post_id, 'post_type' => 'bookdetail' )); if (empty($children)) { $child = array( 'post_type' => 'bookdetail', 'post_title' => $parent_title, 'post_content' => '', 'post_status' => 'publish', 'post_parent' => $post_id, 'post_author' => 1 ); wp_insert_post($child); } } } } add_action('save_post_book', 'add_book_children');
You can obviously tweak this to your own requirements, but hopefully there is enough information here to get the basic workflow added to your site.