0

I have a custom post type for Vacancies, with a Taxonomy of Location set up. What I've achieved is looping through all Locations and then showing underneath associated posts.

Update: Thanks to @YourManDan for the support. Adding 'hide_empty' => false within get_terms was needed to show empty terms. Have updated the code below to include this.

$terms = get_terms( 
    array(
        'taxonomy' => 'location',
        'hide_empty' => false // <- includes the term in query even if there are no posts associated with it
    )
echo '<ul>';
    foreach($terms as $term) {
        $posts = get_posts(
            array(
                'post_type' => 'vacancy', // Post type
                'tax_query' => array(
                    array(
                        'taxonomy' => 'location', // Taxonomy name
                        'field' => 'slug',
                        'terms' => $term->slug
                    )
                ),
                'posts_per_page' => -1
            )
        );
        echo '<li>' . $term->name;
            echo '<ul>';
                foreach($posts as $post) {
                    echo '
                    <li>
                        <a href="' . get_permalink( $post->ID ) . '">' . $post->post_title . '</a>
                    </li>';
                }
            echo '</ul>
        </li>';
    }
echo '</ul>';

This does exactly what I require, in that it loops all locations and outputs links to the vacancy postings.

What I'd now like to do is query underneath any Locations with no posts associated, and show a message instead.

So for something like this:

Birmingham

  • Job 1
  • Job 2

London

  • Job 3
  • Job 4
  • Job 5
  • Job 6

Liverpool (no posts associated)

  • Please email your CV and cover letter and we will be in touch.

From looking into this on here and SO I feel I need to somehow combine what I have with if (has_posts() ) in there somewhere. Or my other thought is to have a second query underneath and possibly use 'operator' => 'NOT EXISTS' in tax_query to find empty ones.

Any support or pointers will be hugely appreciated.

1 Answer 1

0

You can simply add an if statement around your foreach loop to first check to see if there are posts available, and then output a message or loop through the posts.

global $post; // <- Don't forget this at the top of the page!

// ...

$terms = get_terms( 
    array(
        'taxonomy' => 'location',
        'hide_empty' => false // <- includes the term in query even if there are no posts associated with it
    )
);
if ( $terms ) { // <- Don't forget the if wrapper
    foreach ( $terms as $term ) {
        $posts = get_posts( array( /* your parameters */ ) );
        if ( $posts ) { // <- Checks if any posts are in the above query
            foreach ( $posts as $post ) {
                setup_postdata( $post ); // <- Populates the global $post variable with the looped post data, good practice
        
                // ...
    
            }
            wp_reset_postdata(); // <- Resets the global $post variable to what it was, should be used in conjunction with setup_postdata()
        } else {
            // ... echo statement if no posts in term
        }
    }
} else {
    // ... echo statement if no terms
}

The have_posts() function is used in conjunction with WP_Query, not get_posts() like you're using here. When using get_posts(), use if ( $posts ). Read more about WP_Query here.

Generally not a bad idea to wrap any of your foreach query loops with an if statement, just in case there are no posts available. Then, you can output an appropriate message to the site instead of leaving it blank and leaving the user confused.

2
  • Thanks for this Dan. I've improved my code based on your feedback, however it seems my query isn't outputting the empty Taxonomy fields, so where Liverpool has zero posts associated, it simply isn't being output at all.
    – AP_19
    Oct 16, 2023 at 18:55
  • @AP_19 I've reworded my answer to include code for the term query as well, you'll need the hide_empty parameter in your query to let WordPress know to include the terms that have no posts associated with it. By default it doesn't do this. Source
    – YourManDan
    Oct 16, 2023 at 19:07

Your Answer

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

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