3

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?

3
  • What post_type are you using for parent and what post_type for child? Dec 27, 2010 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 Dec 27, 2010 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?) Dec 27, 2010 at 13:27

1 Answer 1

2

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.

7
  • 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 Dec 27, 2010 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. Dec 27, 2010 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); Dec 27, 2010 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 Dec 27, 2010 at 23:09
  • 1
    @jonasl - When you say "acts like an 'attachment'", what specific behavior are you trying to emulate? Dec 28, 2010 at 0:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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