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,

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.

  • How would I check if the flag is true? <?php if($any_in_cat) = true:?>echo'true'<?php else:?>echo 'false'<?php endif;?>? – Gregory Schultz Jul 26 '16 at 7:08
  • I've added that to the code. – Andy Macaulay-Brook Jul 26 '16 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? – Gregory Schultz Jul 26 '16 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. – Andy Macaulay-Brook Jul 26 '16 at 9:14
  • @GregorySchultz that could be mismatched braces or a missing semi colon somewhere. – Andy Macaulay-Brook Jul 26 '16 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(); ?>
  • Error: PHP Warning: Invalid argument supplied for foreach(). – Gregory Schultz Jul 25 '16 at 22:02
  • I forgot the opening and closing parentheses after get_posts. I updated the code. – Fencer04 Jul 25 '16 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';
    }
}
  • 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. – Andy Macaulay-Brook Jul 25 '16 at 13:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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