Custom post type’s slug gets wrong when adding a custom meta box

This strange behaviour is very likely to be caused by the additional form tag you’re adding. The meta boxes are already encapsulated by a form, so adding one yourself in the meta box callback is unnecessary. Removing <form action="<?php bloginfo('url'); ?>" method="get"> and </form> should solve your issues.

EDIT: Seeing as this didn’t solve your issues: I now see the cause for your issue. You’re looping over the child posts and then setting up post data through setup_postdata. You should reset the post data after that, to ensure that no data from your child posts is being used in the rest of the meta boxes. These other meta boxes probably include the slug box, which is why the child slug is used.

Calling wp_reset_postdata at the end of your meta box should do the trick.

EDIT 2:

I’m unsure as to why wp_reset_postdata() doesn’t work, but it’s probably because the post data isn’t in the main query object for some reason on the edit page.

Anyway, the problem does reside in the fact that you’re setting up the global post object yourself through setup_postdata. After you’ve done this for the child posts, the slug or title field seems to be filled through a function that uses the global $post object, and is therefore filled with the child slug or title.

To fix this, you can store the old post object before calling setup_postdata, and use setup_postdata after that to restore the old post object:

function reference_meta_callback( $post ){

  global $post;

  // Store global post object
  $post_old = $post;

  $custom = get_post_custom($post->ID);
  if( isset($custom['reference_id'][0]) ) {
    $reference_id = $custom['reference_id'][0];
  } else {
    $reference_id = '0';
  }

  wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' );

  ?>
      <select name="ref_id" id="ref_id">
        <option value="0" <?php selected($reference_id, '0'); ?>>- choose client -</option>

      <?php
      $args = array( 'numberposts' => -1, 'post_type' => 'page', 'post_parent' => 21);
      $posts = get_posts( $args );
      foreach( $posts as $post ) : setup_postdata( $post ); ?>
        <option value="<?php echo $post->ID; ?>" <?php selected($reference_id, $post->ID); ?>><?php the_title(); ?></option>
      <?php endforeach; ?>

      </select>
  <?php
  // Restore global post object
  $post = $post_old;
  setup_postdata( $post );
} 

Leave a Comment