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'm trying to create sub-posts like this:

/post/info/ /post2/info/

Using wp_insert_post() and I have almost succeeded. I'm setting post_parent to the parent post ID and the post_type needs to be "attachment".

But! The problem is that the post_name needs to be unique so the sub page needs to be info, info2 etc and that's not what I want. So when settings the post_name to the same I'm getting all sub pages on one page when visiting /post/info/ and /post2/info/.

Anyone knows if it's possible to accomplish this?

share|improve this question
    
What post_type are you using for parent and what post_type for child? –  MikeSchinkel Dec 27 '10 at 8:34
    
@MikeSchinkel: post_type for parent is 'post' and for the child it's 'attachemnt'. Not because it's needs to be attachment (it's a post) but else i will get a 404 –  jonasl Dec 27 '10 at 11:46
    
Once you create your custom post type come back to open another question to ask how to get your URLs to work like you want (vs. this question which talks about the duplicating slugs. I think we'd answered that question, no?) –  MikeSchinkel Dec 27 '10 at 13:27
add comment

1 Answer

up vote 1 down vote accepted

Hi @jonasl:

I asked a clarifying question but I'm going to go ahead and at least start to answer.

The function in WordPress core that controls post slugs and adds numbers to them in order to force them to be unique is wp_unique_post_slug(). In WordPress 3.0.3 you can find it on line 2530 in /wp-includes/post.php. I've copied it in full below for your review.

You'll note it says "Attachment slugs must be unique across all types" so if your children are post_type='attachments' then this is what is forcing them to be unique. In addition you'll note that the post types must have 'hierarchical'=>true or it will force them to be unique across all posts.

function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent ) {
  if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
    return $slug;

  global $wpdb, $wp_rewrite;

  $feeds = $wp_rewrite->feeds;
  if ( ! is_array( $feeds ) )
    $feeds = array();

  $hierarchical_post_types = get_post_types( array('hierarchical' => true) );
  if ( 'attachment' == $post_type ) {
    // Attachment slugs must be unique across all types.
    $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
    $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) );

    if ( $post_name_check || in_array( $slug, $feeds ) ) {
      $suffix = 2;
      do {
        $alt_post_name = substr ($slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
        $post_name_check = $wpdb->get_var( $wpdb->prepare($check_sql, $alt_post_name, $post_ID ) );
        $suffix++;
      } while ( $post_name_check );
      $slug = $alt_post_name;
    }
  } elseif ( in_array( $post_type, $hierarchical_post_types ) ) {
    // Page slugs must be unique within their own trees. Pages are in a separate
    // namespace than posts so page slugs are allowed to overlap post slugs.
    $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type IN ( '" . implode( "', '", esc_sql( $hierarchical_post_types ) ) . "' ) AND ID != %d AND post_parent = %d LIMIT 1";
    $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID, $post_parent ) );

    if ( $post_name_check || in_array( $slug, $feeds ) || preg_match( '@^(page)?\d+$@', $slug ) ) {
      $suffix = 2;
      do {
        $alt_post_name = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
        $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_ID, $post_parent ) );
        $suffix++;
      } while ( $post_name_check );
      $slug = $alt_post_name;
    }
  } else {
    // Post slugs must be unique across all posts.
    $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
    $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) );

    if ( $post_name_check || in_array( $slug, $feeds ) ) {
      $suffix = 2;
      do {
        $alt_post_name = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
        $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID ) );
        $suffix++;
      } while ( $post_name_check );
      $slug = $alt_post_name;
    }
  }

  return $slug;
}

If you are not using attachments as children (which I fear you are based on your question) then you can possibly just define the post type as being 'hierarchical'=>true. If you can't do that I might be able to suggest a have to fake it during insert of the post but I can't promise doing so will not cause other posts in WordPress to break.

If you are using attachments and need this maybe you can explain more what you are trying to accomplish so that maybe we can suggest an alternative.

share|improve this answer
    
Thanks Mike, I will try to remove attachment as type and just add 'hierarchical'=>true when using wp_insert_post() and see if it helps. I'm trying to accomplish sub-posts with "more information" about each post: /name-post/more-info/, /post-blah/more-info/ etc –  jonasl Dec 27 '10 at 11:47
    
@jonasl - Suggestion: Create a Custom Post Type called "Info" for your extra information. See wordpress.stackexchange.com/questions/128/#187 and wordpress.stackexchange.com/questions/381/#386. Please come back and let us know how you get on. –  MikeSchinkel Dec 27 '10 at 13:25
    
Sweeet. Sounds exactly like what I need, my code is currently working but ugly. I added the following to single-attachment.php to find the right post based on GUID: $permalink = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $q = "SELECT * FROM $wpdb->posts WHERE post_type = 'attachment' AND guid='$permalink' LIMIT 1"; $pageposts = $wpdb->get_results( $wpdb->prepare($q), OBJECT); –  jonasl Dec 27 '10 at 13:35
    
Hmm, doesn't work. Do you have any examples on how to create a custom post type that acts like 'attacment' ? See copypastecode.com/59000 for my code –  jonasl Dec 27 '10 at 23:09
1  
@jonasl - When you say "acts like an 'attachment'", what specific behavior are you trying to emulate? –  MikeSchinkel Dec 28 '10 at 0:09
show 2 more comments

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.