1

In my loop, I have ten posts with the following categories (slug): group-a, group-a-first and group-b. The loop/query looks like this:

  • Post (group-a)
  • Post (group-b)
  • Post (group-a-first)

What's the best way to check if those posts has a specific category?

I've tried <?php if(in_category('group-a')) ;?>, it does work but it checks every post so I three results: yes, no, no, etc.

What I'm looking for if any post in the loop has a specific category, it outputs either a yes or no.

My query has multiple loops so this the code I'm using:

<?php $args = array('tax_query' => array(array('taxonomy' => 'post-status','field' => 'slug','terms' => array ('post-status-published')))); $query = new WP_Query( $args );?>
    <?php if ( $query->have_posts() ) : $duplicates = []; while ( $query->have_posts() ) : $query->the_post(); ?>

        <?php if ( in_category( 'first-major' ) ) : ?>
            <div class="major"><div class="major-first">
            major and first - <?php the_title();?><br>
            <?php $duplicates[] = get_the_ID(); ?>
</div>
    <?php endif; endwhile; ?>
    <?php $query->rewind_posts(); ?>

        <?php while ( $query->have_posts() ) : $query->the_post(); ?>

        <?php if (( in_category( 'major' ) ) && (!in_category( 'first-major'))) : if ( in_array( get_the_ID(), $duplicates ) ) continue; ?>
            major - <?php the_title(); ?><br>
            <?php $duplicates[] = get_the_ID(); ?>
        <?php endif;?>

    <?php endwhile; ?></div>
    <?php $query->rewind_posts(); ?>  

    <?php while ( $query->have_posts() ) : $query->the_post(); ?>

        <?php if (( in_category( 'major' ) ) && (!in_category( 'first-major'))) : if ( in_array( get_the_ID(), $duplicates ) ) continue; ?>
            major - <?php the_title(); ?><br>
            <?php $duplicates[] = get_the_ID(); ?>
        <?php endif;?>

    <?php endwhile; ?></div>
    <?php $query->rewind_posts(); ?>  

    <?php while ( $query->have_posts() ) : $query->the_post(); ?>

        <?php if ( in_category('group-a')) :?>
            yes
        <?php else :?>
            no
        <?php endif;?>
        <?php if ( in_category( 'group-a-first' ) ) : ?>
            group a and first - <?php the_title(); ?><br>
            <?php $duplicates[] = get_the_ID(); ?>
        <?php endif;?>

    <?php endwhile; ?>
    <?php $query->rewind_posts(); ?>

    <?php while ( $query->have_posts() ) : $query->the_post(); ?>

       <?php if (( in_category( 'group-a' ) ) && (!in_category( 'group-a-first'))) : if ( in_array( get_the_ID(), $duplicates ) ) continue; ?>
            group a - <?php the_title(); ?><br>
            <?php $duplicates[] = get_the_ID(); ?>
        <?php endif;?>

    <?php endwhile; ?>
    <?php $query->rewind_posts(); ?>

    <?php while ( $query->have_posts() ) : $query->the_post(); ?>

        <?php if ( in_category( 'group-b-first' ) ) : ?>
            group b and first - <?php the_title(); ?><br>
            <?php $duplicates[] = get_the_ID(); ?>
        <?php endif;?>

    <?php endwhile; ?>
    <?php $query->rewind_posts(); ?>

    <?php while ( $query->have_posts() ) : $query->the_post(); ?>

        <?php if ( in_array( get_the_ID(), $duplicates ) ) continue; ?>
            <?php the_title();?><br>

    <?php endwhile; wp_reset_postdata(); endif; ?>


</section>

Thanks,

3 Answers 3

1

You can just run through the loop and set a flag:

if ( $query->have_posts() ) : 

    $any_in_cat = false; 

    while ( $query->have_posts() ) : $query->the_post();

        if ( in_category( 'first-major' ) ) :
            $any_in_cat = true;
        endif; 

    endwhile;

$query->rewind_posts();

/* if $any_in_cat == true at this point then at least one 
   of the posts has the category 'first-major'
*/

if( true == $any_in_cat ) {
    echo 'true';
} else { 
    echo 'false';
}

I've added your conditional check. Note that it is all PHP, so you don't want the opening and closing tags where you have them in your comment. I prefer the brace notation myself as it suits every case of nested conditionals and is really clear to read. Lastly you need the double-equals sign to test equality. = is the assignment operator, so when you say if ( $any_in_cat = true ) then you are setting $any_in_cat to true and also the condition will always be true. Even if ( $any_in_cat = false ) is true because you are testing the success of the assignment. It's a slip we all make and is easier to debug if you get in the habit of writing the condition as if( true == $any_in_cat ) Then if you slip and use a single = you'll get an error message as you can't make an assignment to true.

You're re-running your loop several times, so it might be possible to simplify your code somewhat too, but that's another question and not directly WP related.

9
  • How would I check if the flag is true? <?php if($any_in_cat) = true:?>echo'true'<?php else:?>echo 'false'<?php endif;?>? Commented Jul 26, 2016 at 7:08
  • I've added that to the code. Commented Jul 26, 2016 at 8:33
  • Last question (and yes I am reducing the number of re-running the loop) how would I pass those variables down to another loop. use $any_cat = [] in the if while query loop? Commented Jul 26, 2016 at 9:12
  • You'd just test it as I've shown further down in your code. That's why I showed setting $any_in_cat = true; in my answer: I assumed you wanted an easy way of accessing that later on. Commented Jul 26, 2016 at 9:14
  • @GregorySchultz that could be mismatched braces or a missing semi colon somewhere. Commented Jul 26, 2016 at 19:49
1

You can create a separate function to check your array of posts contains a post with that category. It will basically do what you are now but it will allow you to call the function once instead of each time through the loop. You would put this code in your functions.php file:

function does_array_contain_category( $categories, $posts ){
    foreach( $posts as $post) {
        if( in_category( $categories, $post ) ){
            return true;
        }
    }
    return false;
}

You could then call this function in your loop by doing this:

<?php 
    //$in_group_a will be true or false for use wherever you need it.
    $in_group_a = does_array_contain_category( array( 'group_a' ), $query->get_posts() ); 
    while ( $query->have_posts() ) : $query->the_post(); ?>

    <?php endwhile; ?>
<?php $query->rewind_posts(); ?>
2
  • Error: PHP Warning: Invalid argument supplied for foreach(). Commented Jul 25, 2016 at 22:02
  • I forgot the opening and closing parentheses after get_posts. I updated the code.
    – Fencer04
    Commented Jul 25, 2016 at 23:09
-2

is_category() tests to see if you are displaying a category archive, but you are displaying a single post, so this will always return false

in_category() tests to see if a given post has a category in that specific category and must be used in The Loop, but you are trying to figure out what the category is, before you get to the loop.


if ( is_single() ) {
    $cats = wp_get_post_categories($posts[0]->ID);
    $first_cat = '';
    if ($cats) {
        $first_cat = $cats[0];
    }
    if ($first_cat == 7 ) {
        include 'wp-loop2.php';
    } else {
        include 'wp-loop.php';
    }
}
1
  • But the OP is using in_category, is in a situation where false == is_single() and doesn't have an array $posts. $query->posts contains all the posts, but even then you are just checking the categories of the first post. Commented Jul 25, 2016 at 13:17

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.