Question

Info about my setup:

  • I have a custom post type called 'Treatments'
  • Each treatment is categorised in to up to 3 taxonomy types - treatment categories - 'beautysalon' 'skinclicnic' 'spadays' and these have lots of different categories under them.
  • A treatment can also be attached to a brand, also a taxonomy - 'brands'

What I am trying to achieve:

Display the treatments on the treatment categories archive pages but divided by the brands taxonomy, and also include treatments within the category that are not attached to a brand taxonomy. So the archive pages would look something like this:

Treatment Category Title

Brand 1

  • Treatment A
  • Treatment B
  • Treatment C

Brand 2

  • Treatment D
  • Treatment E
  • Treatment F

(No Brand)

  • Treatment J
  • Treatment K
  • Treatment L

I have made a taxonomy.php template handle this on every taxonomy page, but...

My issues are:

1) I cannot find a way to stop empty treatment category titles from being displayed. I think I need to insert a foreach or IF statement somewhere, or possibly change the $args array so only the categories with treatments in are returned. I have tried including hide_empty statements, but that doesn't seem to work either.

2) As I set the query by brand taxonomy, I cannot make treatments display that are not attached to any brand. Maybe I need to have 2 loops?

Here is my code, any help?

<?php

// grab current page info
$queried_object = get_queried_object();
$taxonomy = $queried_object->taxonomy;
$term_id = $queried_object->term_id;

// fetch the terms for brands tax
$terms = get_terms( 'brands', array(
    'orderby'    => 'title',
        'order'   => 'ASC',
        'hide_empty' => true,
) );

the_archive_title( '<h1 class="page-title">', '</h1>' );

// now run a query for each brand
foreach( $terms as $term ) {

    $args = array(
        'post_type' => 'treatments',
        'nopaging' => true,
        'orderby' => 'title',
        'order'   => 'ASC',
        'hide_empty'   => true,
        'tax_query' => array(
            'relation' => 'AND',
            array(
                'taxonomy' => 'brands',
                'terms' => $term->slug,
                'field' => 'slug',
                'operator' => 'IN'
            ),
            array(
                'relation' => 'OR',
                array(
                    'taxonomy' => 'beautysalon',
                    'terms' => $queried_object->slug,
                    'field' => 'slug',
                    'operator' => 'IN'
                ),
                array(
                    'taxonomy' => 'skinclinic',
                    'terms' => $queried_object->slug,
                    'field' => 'slug',
                    'operator' => 'IN'
                ),
                array(
                    'taxonomy' => 'spadays',
                    'terms' => $queried_object->slug,
                    'field' => 'slug',
                    'operator' => 'IN'
                ),
            )
        )
    );
    $query = new WP_Query( $args );

// output the term name in a heading tag
echo'<h2>' . $term->name . '</h2>';
// output the post titles in a list
echo '<ul>';
while ( $query->have_posts() ) : $query->the_post(); ?>

        <li id="post-<?php the_ID(); ?>">
            <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
        </li>

        <?php endwhile;

    echo '</ul>';
    wp_reset_postdata();

} ?>
Was it helpful?

Solution

1) Fixing this was surprisingly simple - I wrapped the category name request in if have_posts and that got rid of the empty values

2) I had to include a secondary loop using 'operator' => 'NOT IN' to list the treatments that were not in a taxonomy.

I am sure there is a leaner and better way to do the following, but this for now serves what I want to do.

Final code

<?php

            // grab current page info
            $queried_object = get_queried_object();
            $taxonomy = $queried_object->taxonomy;
            $term_id = $queried_object->term_id;

            // fetch the terms for brands tax
            $terms = get_terms( 'brands', array(
                'orderby'    => 'title',
                'order'   => 'ASC',
                'hide_empty' => true,
                'posts_per_page' => -1,
            ) );

            the_archive_title( '<h1 class="page-title">', '</h1>' );

            // now run a query for each brand
            foreach( $terms as $term ) {

                $args = array(
                    'post_type' => 'treatments',
                    'nopaging' => true,
                    'orderby' => 'title',
                    'order'   => 'ASC',
                    'hide_empty'   => true,
                    'posts_per_page' => -1,
                    'tax_query' => array(
                        array(
                            'taxonomy' => 'brands',
                            'terms' => $term->slug,
                            'field' => 'slug',
                            'operator' => 'IN',
                            'hide_empty'   => true,
                        ),
                        array(
                            'relation' => 'OR',
                            array(
                                'taxonomy' => 'beautysalon',
                                'terms' => $queried_object->slug,
                                'field' => 'slug',
                                'operator' => 'IN'
                            ),
                            array(
                                'taxonomy' => 'skinclinic',
                                'terms' => $queried_object->slug,
                                'field' => 'slug',
                                'operator' => 'IN'
                            ),
                            array(
                                'taxonomy' => 'spadays',
                                'terms' => $queried_object->slug,
                                'field' => 'slug',
                                'operator' => 'IN'
                            ),
                        )
                    )
                );
                $query = new WP_Query( $args );

// only show a header if there is posts present 
if( $query->have_posts() ) :
echo'<h2>' . $term->name . '</h2>';
echo '<ul>';
while ( $query->have_posts() ) :
$query->the_post(); ?>

                <li id="post-<?php the_ID(); ?>">
                    <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                </li>

            <?php endwhile;

echo '</ul>';
endif;
wp_reset_postdata();
}
        // second query - everything not in a brand
        $args = array(
            'post_type' => 'treatments',
            'nopaging' => true,
            'orderby' => 'title',
            'order'   => 'ASC',
            'tax_query' => array(
                array(
                    'taxonomy' => 'brands',
                    'terms' => $term->slug,
                    'field' => 'term_id',
                    'operator' => 'NOT IN',
                ),
                array(
                    'relation' => 'OR',
                    array(
                        'taxonomy' => 'beautysalon',
                        'terms' => $queried_object->slug,
                        'field' => 'slug',
                        'operator' => 'IN'
                    ),
                    array(
                        'taxonomy' => 'skinclinic',
                        'terms' => $queried_object->slug,
                        'field' => 'slug',
                        'operator' => 'IN'
                    ),
                    array(
                        'taxonomy' => 'spadays',
                        'terms' => $queried_object->slug,
                        'field' => 'slug',
                        'operator' => 'IN'
                    ),
                )
            ));
            $the_query = new WP_Query( $args );

            if ( $the_query->have_posts() ) :
                echo '<h2>Other ' . $queried_object->name . ' Treatments</h2>';
                while ( $the_query->have_posts() ) : $the_query->the_post();
                ?>

                <li id="post-<?php the_ID(); ?>">
                    <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                </li>

            <?php endwhile;
        endif;
        echo '</ul>';
        wp_reset_postdata();
        ?>
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top