How to output custom post type title on custom page with category next to it?

All we need is an easy explanation of the problem, so here it is.

I have a website for an organisation, and I created a new page for the leadership team. I ran a query, looking for the "member"-type that have the category of "Leadership". So far, when I output this on the page, it works fine. I also have child categories of "President" and "Secretary" that I want to display beside each leader’s name. However, as soon as I call get_the_category(), everything gets messed up, and only one result is output, and the President category somehow disappears and the post with the category of "President" gets "Secretary" displayed next to it.
This is the relevant code:

<?php
    $leaderQuery = new WP_Query(array(
        'posts_per_page' => -1,
        'post_type' => 'member',
        'cat_slug' => "Leadership"
    ));
    
    //var_dump($leaderQuery);
    
    while($leaderQuery->have_posts())
    {
        $postCategories = get_the_category($leaderQuery->the_post());
        //$categoryDescription = category_description($postCategories[0]);
        //var_dump($postCategories);
                $leaderQuery->the_post(); ?>
                <div class="post-item">
                    <p class="headline headline--small"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> - <?php echo get_the_category($leaderQuery->the_post())->name; ?></p>
                </div>
            <?php
    }
    wp_reset_postdata();
    echo paginate_links();
  ?>

var_dump($leaderQuery->the_post()) does not contain category information, but var_dump($postCategories) does. This is the var_dump($postCategories):

array (size=2)
  0 => 
    object(WP_Term)[1446]
      public 'term_id' => int 7
      public 'name' => string 'Joint Secretary' (length=15)
      public 'slug' => string 'joint-secretary' (length=15)
      public 'term_group' => int 0
      public 'term_taxonomy_id' => int 7
      public 'taxonomy' => string 'category' (length=8)
      public 'description' => string 'B' (length=1)
      public 'parent' => int 6
      public 'count' => int 1
      public 'filter' => string 'raw' (length=3)
      public 'cat_ID' => int 7
      public 'category_count' => int 1
      public 'category_description' => string 'B' (length=1)
      public 'cat_name' => string 'Joint Secretary' (length=15)
      public 'category_nicename' => string 'joint-secretary' (length=15)
      public 'category_parent' => int 6
  1 => 
    object(WP_Term)[1441]
      public 'term_id' => int 6
      public 'name' => string 'Leadership' (length=10)
      public 'slug' => string 'leadership' (length=10)
      public 'term_group' => int 0
      public 'term_taxonomy_id' => int 6
      public 'taxonomy' => string 'category' (length=8)
      public 'description' => string '' (length=0)
      public 'parent' => int 0
      public 'count' => int 2
      public 'filter' => string 'raw' (length=3)
      public 'cat_ID' => int 6
      public 'category_count' => int 2
      public 'category_description' => string '' (length=0)
      public 'cat_name' => string 'Leadership' (length=10)
      public 'category_nicename' => string 'leadership' (length=10)
      public 'category_parent' => int 0

This is the wrong data for the current post that is actually output on the page, and of the two, only one is displayed, and the other gives its category information.

How do I make it so each post correctly retrieves the category name and displays it alongside the post title?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

$leaderQuery->the_post() should only be called once, right after the loop starts:

while ( $leaderQuery->have_posts() ) {
    $leaderQuery->the_post(); // call it just once
    ...
}

I could also see you’re not correctly retrieving the ID of the current post in the loop, so the correct way is use get_the_ID().

$postCategories = get_the_category( get_the_ID() );           // like this
$postCategories = get_the_category($leaderQuery->the_post()); // not this

But within a loop, you can simply call get_the_category() like that, i.e. without any parameters.

And note that get_the_category() returns an array of term objects, so if you just want to get the name of the first category in that array, then you can do:

// Get all categories (term objects) assigned to the current post.
$postCategories = get_the_category();

// Get the first category's name.
$first_cat_name = ( ! empty( $postCategories ) ) ? $postCategories[0]->name : '';

But if you want to display all the categories, then you can simply use the_category().

And note that for custom taxonomies, you would:

Update

Actually, in your WP query’s args, that cat_slug is not a valid parameter for WP_Query. Instead, it should be category_name, but remember that it expects a slug and not the category name, e.g. my-category and not My Category.

Also, you could use something like so to display a specific category name only if the current post is in that category:

if ( in_category( 'Leadership' ) ) {
    echo 'In the Leadership category';
}

// Or after closing the PHP tag ( ?> ):
//<?php echo in_category( 'Leadership' ) ? 'In the Leadership category' : ''; ?>

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

Leave a Reply