Link to home
Start Free TrialLog in
Avatar of Crazy Horse
Crazy HorseFlag for South Africa

asked on

Nest child records of parent custom post type

I am outputting all custom post type names, parents and children of those parents but I want the children to be nested within the parent in a list item. Currently they are all outputted at the same level in the current taxonomy.

  <?php $custom_terms = get_the_terms( $post->ID, 'product_cats' ); ?>
   <ul id="nav">
      <?php foreach($custom_terms as $custom_term) {
         wp_reset_query();
            $args = array(
                'post_type' => 'products',
                'numberposts' => '-1',
                'posts_per_page' => -1,
                'orderby' => 'name',
                'tax_query' => array(
                    array(
                        'taxonomy' => 'product_cats',
                        'field' => 'slug',
                        'numberposts' => '-1',
                        'posts_per_page' => -1,
                        'orderby' => 'name',
                        'terms' => $custom_term->slug,
                    ),
                ),
            );

         $loop = new WP_Query($args);
         if($loop->have_posts()) {

         $current_id = get_the_ID();
         while($loop->have_posts()) : $loop->the_post(); if($post->ID!=97){ ?>
      <li<?php if($current_id == $post->ID){?> class="current" <?php } ?> >
         <a href="<?php echo get_permalink();?>"><?php echo get_the_title();?></a>
      </li>
      <?php }  endwhile;
         }
         }

         wp_reset_postdata(); 

         ?> 

Open in new window


So, the output should look something like:

Item 1
Item 2
      Child 1
      Child 2
Item 3
Item 4
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Crazy Horse

ASKER

Thanks Julian,

I probably don't understand what you mean exactly but I tried something like this:

                <li<?php if($current_id == $post->ID){?> class="current" <?php } ?> >
                <?php if ($loop->post->post_parent === 0): ?>
                    <a href="<?php echo get_permalink();?>"><?php echo get_the_title();?>
                <?php elseif ($loop->post->post_parent !== 0): ?>
                    <ul>
                        <li><?php the_title(); ?></li>
                    </ul>
                <?php endif; ?>
                    </a>
                </li>

Open in new window


This is pretty silly really as it is just still showing the child records separately instead of as part of the parent.
I need to know how you are retrieving posts. I am assuming you are getting top level posts and the for each of those checking for child posts?

Or do you get everything at once - in which case how are your "recognizing" the hierarchy.
How it currently is, is that you click on an item and go to the detail page ie: single-item.php then in the left sidebar it shows you all the items for that particular category that the item is associated with.

So, first you have to get the category associated with the item. Then loop through all parent and children items of that category.

This is the loop which gets the items:

            $args = array(
                'post_type' => 'products',
                'numberposts' => '-1',
                'posts_per_page' => -1,
                'orderby' => 'name',
                'tax_query' => array(
                    array(
                        'taxonomy' => 'product_cats',
                        'field' => 'slug',
                        'numberposts' => '-1',
                        'posts_per_page' => -1,
                        'orderby' => 'name',
                        'terms' => $custom_term->slug,
                    ),
                ),
            );

Open in new window


This loop is just getting everything for the relevant category and shows me all parent and children records. If I had this in then I just get the parent items:

'post_parent' => 0

Open in new window


I don't know how to 'attach' the children to the parent in an unordered list in amongst the items with only parent records.

So, instead of getting what I want:

Item 1
Item 2
      Child 1
      Child 2
Item 3
Item 4

I get:

Item 1
Item 2
Child 1
Child 2
Item 3
Item 4
I found a better way to do this which is to just use wp_list_pages. The issue now though is that it lists EVERYTHING instead of just for the current category. I am able to get the current category but not sure how to use that to filter wp_list_pages.

$custom_terms = get_the_terms( $post->ID, 'product_cats' );

$args = array(
    'post_type' => 'products',
                    'tax_query' => array(
                    array(
                        'taxonomy' => 'product_cats',
                        'field' => 'slug',
                        'numberposts' => '-1',
                        'posts_per_page' => -1,
                        'orderby' => 'name',
                        'terms' => $custom_terms[0]->slug,
                    ),
                ),
);
wp_list_pages( $args ); 

Open in new window

Can you post what the data looks like.

The method I posted should work but will just need to be adapted for the dataset.
With the wp_list_pages it lists all the products post types including children, nicely formatted, exactly as I want it actually. But the only problem is that it is showing all products instead of just the ones for that specific product category. For example, if I go to a particular pair of shoes detail page, then down the side it should only list other shoes and their children EG: I have shoelaces as a child.

- Running shoes
- Squash shoes
      -shoe laces
- Smart shoes

The html I get back from wp_list_pages as is:

<li class="pagenav">Pages<ul>
        <li class="page_item page-item-681"><a
                href="http://localhost:8888/product/parent1/">Parent1</a></li>
        <li class="page_item page-item-659 page_item_has_children current_page_item"><a
                href="http://localhost:8888/product/parent2/" aria-current="page">Parent2</a>
            <ul class="children">
                <li class="page_item page-item-688"><a
                        href="http://localhost:8888/product/parent2/child1/">Child1</a></li>
                <li class="page_item page-item-686"><a
                        href="http://localhost:8888/product/parent2/child2/">Child2</a>
                </li>
            </ul>
        </li>
        <li class="page_item page-item-495"><a href="http://localhost:8888/product/parent3/">Parent3</a></li>
        // more products and closing tags

Open in new window

not sure where we are with this question - is it working for you?
Where does the HTML come from?
Hi Julian, no, still not working. The html is just the output from the wp_list_pages. But wp_list_pages doesn't seem to let you put in a custom taxonomy.

I have posted the code again but commented it to try explain better.

// get current taxonomy/category
$custom_terms = get_the_terms( $post->ID, 'product_cats' );

$args = array(
   // get custom post type 'products'
    'post_type' => 'products',
                    'tax_query' => array(
                    array(
                        // get product_cats taxonomy
                        'taxonomy' => 'product_cats',
                        'field' => 'slug',
                        // this is meant to be the taxonomy term to filter by but it is being ignored, hence the wp_list_pages() function listing ALL product post types instead of the ones just for the current taxonomy
                        'terms' => $custom_terms[0]->slug,
                    ),
                ),
);
wp_list_pages( $args );

Open in new window



So, what I am trying to say is that wp_list_pages() function is outputting the data in the format I want in that it is showing parent and children pages and indenting correctly ie: the children are nested inside the parent ie: <ul> inside the <li>

But instead of just showing shoes for example, it is showing shirts, pants, absolutely everything.