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 creating a theme with a custom post type for team members, I've also got the following page structure:

about  <-- this is a page
about/team-members  <-- this is a page, lists all the team members
about/team-members/joe-bloggs  <-- this is a custom post type (team member) entry

The third structure here uses the about and team member pages, but goes on to use the custom post type slug to make it look like it's parents are team member and about. I've achieved this by setting the following options on the custom post type:

'rewrite' => array( 'slug' => 'about/team-members', 'with_front' => false)

This works great, however when I get down to the team member post level I no longer get the current-page, current-ancestor classes on the parent pages. I know why this is, because we're not technically on a pagea parent of those pages, however is there a way I can trick/fix/bodge so the pages DO apear as parents?

I had achieved this nicely by using pages for team members, however a custom post type was chosen instead for easy of use for the administrator.

Thanks guys + girls!

share|improve this question

This question has an open bounty worth +150 reputation from ndm ending in 7 days.

The question is widely applicable to a large audience. A detailed canonical answer is required to address all the concerns.

While assigning a parent of a different type is rather simple and explained in the answer of @Bainternet, the following problem is unsolved: The parent page hierachy is not being reflected in the navigation menu, instead it will always mark the default posts page as active (and only that one single page, not its parents - this is identical to the behavior with post post types).

you need to set team-members page id as your custom post type post_parent. –  Bainternet Mar 28 '11 at 18:41
I don't see that option in the register_post_type documentation, can you assist? –  Ben Everard Mar 28 '11 at 19:00

2 Answers 2

When Working with pages you can select a parent page and that value is saved as the parent page id number in the child page's post_parent field in the database.

in your case you are using a custom post type so you would need to create your own metabox for the parent page , something like:

/* Define the custom box */
add_action('add_meta_boxes', 'child_cpt_add_custom_box');

/* Adds a box to the main column on the custom post type edit screens */
function child_cpt_add_custom_box() {
    add_meta_box('child_cpt', __( 'My child_cpt parent'),'team_member_inner_custom_box','team_member');

/* Prints the box content */
function team_member_inner_custom_box() {
    global $post;
    // Use nonce for verification
    wp_nonce_field( plugin_basename(__FILE__), 'team_member_inner_custom_box' );
    echo 'Select the parent page';
    $mypages = get_pages();
    echo '<select name="cpt_parent">';
    foreach($mypages as $page){     
        echo '<option value="'.$page->ID.'"';
        if ($page->ID == $post->post_parent) {echo ' selected';}
        echo '>"'.$page->post_title.'</option>';
    echo '</select>';
/* Do something with the data entered */
add_action('wp_insert_post_data', 'myplugin_save_postdata');

/* When the post is saved, saves our custom data */
function myplugin_save_postdata( $data, $postarr ) {
    global $post;
      // verify this came from the our screen and with proper authorization,
      // because save_post can be triggered at other times

      if ( !wp_verify_nonce( $_POST['team_member_inner_custom_box'], plugin_basename(__FILE__) ) )
          return $data;

      // verify if this is an auto save routine. 
      // If it is our form has not been submitted, so we dont want to do anything
      if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
          return $data;
      // OK, we're authenticated: we need to find and save the data

     if ($post->post_type == "team_member")}
    $data['post_parent'] = $_POST['cpt_parent'];

    return $data;

it has nothing to do with register_post_type you are "tricking WordPress to thing that this is a child page of another post type (page). let me know if this helps.

share|improve this answer
Righto, so I can see how this "fools" WordPress to think a specific page is it's parent, however it's not adding the page parent class to the parent page when I wp_list_pages. –  Ben Everard Mar 28 '11 at 21:11
I've noticed this also messes with my slug / permalink structure... :S –  Ben Everard Mar 29 '11 at 19:52
i'm trying to achieve the same thing as Ben but i use wp_nav_menu - the post_parent is about/team-members but the navigation highlights the parent item of my "normal" blog posts ... any other idea how i could fix this? –  pkyeck Oct 10 '11 at 14:05
@BenEverard: Did you find a solution for the permalink structure mess? –  abaumg Nov 15 '11 at 22:05

I went with a custom walker to achieve something similar... avoids needs for custom fields, but all posts of a type have to sit below the same point in the page tree.

class Walker_Page_CustomPostTypeHack extends Walker_Page {
    function walk($elements, $max_depth) {
        $called_with = func_get_args();
        // current page is arg 3... see walk_page_tree for why
        $current_page = $called_with[3];

        // if there's no parent - see if we can find one.
        // some ACF options would be an easy way to make this configurable instad of constants
        if ($current_page === 0) {
            global $wp_query;
            $current_post = $wp_query->get_queried_object();
            switch ($current_post->post_type) {
                case 'course':
                    $current_page = POST_COURSES;
                case 'project':
                    $current_page = POST_PROJECTS;
                case 'story':
                    $current_page = POST_STORIES;

        // now pass on into parent
        $called_with[3] = $current_page;
        return call_user_func_array(array('parent', 'walk'), $called_with);

share|improve this answer

Your Answer


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.