1

I need help with my query that uses rewind_posts so that if a post is in a particular category, it moves to the top. What I would like to do is have a query that splits posts into a two-column page (left and right divs) and if a post is in a category called First, it's at the top of the list in the left column.

I was able to do this task doing two different queries but I'm having problems merging into one query. I tired to do it myself but the $i++ confused me so I'm asking for help on how to merge two separate queries into one.

This is the first query where if any post belongs in a first or second category, they are brought to the top:

<?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' ) ) : ?>
        <?php the_title();?><br>
        <?php $duplicates[] = get_the_ID(); ?>

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

<?php while ( $query->have_posts() ) : $query->the_post(); ?>
    <?php if ( in_category( 'Second' ) ) : if ( in_array( get_the_ID(), $duplicates ) ) continue; ?>

        <?php the_title(); ?><br>
        <?php $duplicates[] = get_the_ID(); ?>

    <?php endif; 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; ?>

This is the query that splits posts into two columns:

<?php $args = array(
'tax_query' => array(
array(
'taxonomy' => 'post-status',
'field' => 'slug',
'terms' => array ('post-status-published')
))); $wp_query = new WP_Query( $args ); ?>
<div class="left">
<?php if (have_posts()) : while(have_posts()) : $i++; if(($i % 2) == 0) : $wp_query->next_post(); else : the_post(); ?>

<?php the_title(); ?><br>

<?php endif; endwhile; ?></div><?php else:?>
<?php endif; ?>

<?php $i = 0; rewind_posts(); ?>
<div id="right">

<?php if (have_posts()) : while(have_posts()) : $i++; if(($i % 2) !== 0) : $wp_query->next_post(); else : the_post(); ?>

<?php the_title(); ?><br>

<?php endif; endwhile; ?></div><?php else:?>
<?php endif; ?>

An example of what I'm trying to accomplish:

Title - First      | Title
Title - Second     | Title
Title              | Title

Thanks!

3
  • first and second on the left Commented Jul 12, 2016 at 5:51
  • @PieterGoosen Added an example and yes, your comment is correct. Commented Jul 12, 2016 at 7:31
  • @PieterGoosen After Second, it's whatever is the first post in the queryby default (publish date), minus the posts in first and second Commented Jul 12, 2016 at 9:08

2 Answers 2

1

REWORKED APPROACH

Due to this becoming a bit of tameletjie due to styling issues, lets rework everything and look at a different approach

I think what we should do here is to rather shuffle the $posts array through usort() to get the posts sorted in the order we want, and then there after we can run the loop normally

Create our query:

<?php 
$args = array(
    'tax_query' => array(
        array(
            'taxonomy' => 'post-status',
            'field' => 'slug',
            'terms' => array ('post-status-published')
        )
    )
); 
$query = new WP_Query( $args ); 

Now that we have ran our query, we need to get the $posts property from $query and sort it. So this part will go below our query: (NOTE: This is completely untested)

if ( $query->have_posts() ) :
    // Now we will use usort to sort the posts array
    @usort( $query->posts, function ( $a, $b ) // @ hides the bug before PHP 7
    {
        // Assign sortable values for categories to sort posts by
        $array = ['a' => $a, 'b' => $b];
        $sort_order_a = '';
        $sort_order_b = '';
        foreach ( $array as $key=>$p ) {
            if ( in_category( 'First', $p ) ) {
                ${'sort_order_' . $key} = 1;
            } elseif ( in_category( 'Second', $p ) ) { 
                ${'sort_order_' . $key} = 2;
            } else {
                ${'sort_order_' . $key} = 3;
            }
        }

        // Now that we have a custom sorting order, lets sort the posts
        if ( $sort_order_a !== $sort_order_b ) {
            // Make sure about <, change to > to change sort order
            return $sort_order_a < $sort_order_b; 
        } else { 
            /** 
             * Sort by date if sorting order is the same, 
             * again, to change sort order, change > to <
             */
            return $a->post_date > $b->post_date;
        }
    });

    // Our posts is now sorted, run the loop normally
    // Define our counter to set our columns
    $counter = 0;
    $midpoint = ceil( $query->post_count / 2 );

    while ( $query->have_posts() ) :
        $query->the_post();
            // set our left div on first post
            if ( 0 == $counter ) : 
                ?>
                <div id="left">
                <?php
            endif;

            // Close our left div and open the right one on midpoint
            if ( ( $counter + 1 ) == $midpoint ) :
                <?php
                </div>
                <div id="right">
                <?php
            endif;

            // Lets output the posts with different styling
            if ( in_category( 'First', get_the_ID() ) {
                // Apply styling for category First and display title
                    the_title();
            } elseif ( in_category( 'First', get_the_ID() ) {
                // Apply styling for category Second and display title
                    the_title();
            } else {
                // Apply styling for other posts and display title
                    the_title();
            }

            /**
             * Lets close the div and bail if we have only one post, 
             * or if we are on the last post
             */
            if (    1 == $post_count 
                 || ( $counter + 1 ) == $post_count
            ) :
                ?> 
                </div>
                <?php
            endif;

            // Update our counter
            $counter++;

    endwhile;
    wp_reset_postdata();
endif;

ORIGINAL ANSWER

Your second block of code won't work and beats the whole reason for your previous question. Just a note on that code, you should not be using $wp_query as a local variable, it is is a reserved global variable which is intenally used in WordPress to hold the main query object. Breaking this global will break a lot of other stuff. What you are doing is what query_posts() does, that is also why you should never use query posts.

Your issue is that your counter is wrongly updated, thus it wrongly adds your divs. What we need to do is to only update our counder in our conditional statements to prevent posts being double counted and therefor stuufing out layout.

We will only use the first loop and modify that accordingly. The only tricky part will be when to open and close divs

EDIT

Due to the code getting a bit techincal, I scrapped my original idea. We will still use the code in block one, except, it would be much easier to loop through the posts as before and create a new array and finally loop through that array and display the posts.

<?php 
$args = array(
    'tax_query' => array(
        array(
            'taxonomy' => 'post-status',
            'field' => 'slug',
            'terms' => array ('post-status-published')
        )
    )
); 
$query = new WP_Query( $args ); 

if ( $query->have_posts() ) :

    /**
     * Get the amount of posts in the loop, this will be used
     * to calculate when to open and close our divs
     */
    $post_count = $query->post_count;

    /**
     * Get a midpoint to break the div into left and right
     */
    $midpoint = ceil( $post_count / 2 );

    $duplicates  = []; 
    $post_titles = [];

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

        if ( in_category( 'First' ) ) :
            $post_titles[] = apply_filters( 'the_title', get_the_title() );
            $duplicates[] = get_the_ID(); 

        endif; 
    endwhile; 

    $query->rewind_posts();

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

        if ( in_category( 'Second' ) ) : 
            if ( in_array( get_the_ID(), $duplicates ) ) 
                continue;

            $post_titles[] = apply_filters( 'the_title', get_the_title() );
            $duplicates[] = get_the_ID();

        endif; 
    endwhile;

    $query->rewind_posts();          

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

        if ( in_array( get_the_ID(), $duplicates ) ) 
            continue; 

        $post_titles[] = apply_filters( 'the_title', get_the_title() );

    endwhile; 
    wp_reset_postdata(); 

    // Now that we have an array of post titles sorted, lets display them
    foreach ( $post_titles as $key=>$post_title ) :
        // Open our left div
        if ( 0 == $key ) : 
            ?>
            <div id="left">
            <?php
        endif;

        // Close our left div and open the right one on midpoint
        if ( ( $key + 1 ) == $midpoint ) :
            <?php
            </div>
            <div id="right">
            <?php
        endif;

        // Display the post title
        echo $post_title . '</br>';

        /**
         * Lets close the div and bail if we have only one post, 
         * or if we are on the last post
         */
        if (    1 == $post_count 
             || ( $key + 1 ) == $post_count
        ) :
            ?> 
            </div>
            <?php
            break;
        endif;

    endforeach;

endif; 
?>

IMPORTANT NOTE:

Al code is untested and can be improved as you see fit. Due to being untested, there might be slight syntax errors or small bugs

2
  • First, thanks again for helping me out. Second, I have an error on line 14: unexpected _ on ${'sort_order'_$key} = 1; Commented Jul 16, 2016 at 14:04
  • I have updated my code. As I stated, there might be bugs as I cannot test it Commented Jul 18, 2016 at 11:03
0

It's complete. This is my final code:

// the query. Only show posts that belong to the taxonomy called "post-status" and they have a slug called "post-status-published"
<?php $args = array('tax_query' => array(array('taxonomy' => 'post-status','field' => 'slug','terms' => array ('post-status-published')))); $query = new WP_Query( $args );?>

// the loop. Also gets variables to false and enables the variable "duplicate".
<?php if ( $query->have_posts() ) : $firstonly = false; $major = false; $groupa = false; $groupb = false; $groupc = false; $groupd = false; $duplicates = []; while ( $query->have_posts() ) : $query->the_post(); ?>


// checks if any post in the loop belongs to a certain category. If any post with those category is in the loop, the variable is changed to "true". Also adds the "Post ID" in that category to the "duplicate" variable.
<?php if ( in_category('first') ) : ?>
    <?php $firstonly = true; ?>
    <?php $duplicates[] = get_the_ID(); ?>
<?php endif; ?>
<?php if ( in_category(array('major','major-first') ) ) : ?>
    <?php $major = true; ?>
    <?php $duplicates[] = get_the_ID(); ?>
<?php endif; ?>
<?php if ( in_category(array('group-a-first','group-a')) ) : ?>
    <?php $groupa = true; ?>
    <?php $duplicates[] = get_the_ID(); ?>
<?php endif;?>
<?php if ( in_category(array('group-b-first','group-b')) ) : ?>
    <?php $groupb = true; ?>
    <?php $duplicates[] = get_the_ID(); ?>
<?php endif;?>
<?php if ( in_category(array('group-c-first','group-c')) ) : ?>
    <?php $groupc = true; ?>
    <?php $duplicates[] = get_the_ID(); ?>
<?php endif;?>
<?php if ( in_category(array('group-d-first','group-d')) ) : ?>
    <?php $groupd = true; ?>
    <?php $duplicates[] = get_the_ID(); ?>
<?php endif;?>


// Close the loop and rewind the query
<?php endwhile; endif; ?>
<?php $query->rewind_posts(); ?>


// The output of the loop. Only show the output if the above is set to true.
<?php if ($major == true):?>
    <div class="group-major">
    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'major-first'):?>
                <div class="major-first">
                major first - <?php print $postData->post_title;?><br>
                </div>
            <?php endif;?>
    <?php } ?>
    <div class="group-sorted">
    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'major'):?>
                <div class="post">
                major - <?php print $postData->post_title;?><br>
                </div>
            <?php endif;?>
    <?php } ?>
    </div></div>
<?php endif;?>
<?php if ($firstonly == true):?>
    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            first - <?php print $postData->post_title;?><br>
    <?php } ?>
<?php endif;?>
<?php if (($groupa == true) or ($groupb == true) or ($groupc == true) or ($groupd == true)):?>
    <?php if (($groupa == true) && ($groupb == false)):?>
        group solo start<br>
        <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-a-first'):?>
                group a first (only) - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>

    <?php else:?>
        group multi start<br>
        <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-a-first'):?>
                group a first (multi) - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>

    <?php endif;?>

    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-a'):?>
                group a - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>

    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-b-first'):?>
                group b first - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>
    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-b'):?>
                group b - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>

    <?php if (( true == $groupa ) && (false == $groupb) && (false == $groupc) && (false == $groupd)) :?>
        solo end<br>
    <?php endif;?>
    <?php if (( true == $groupa ) && (true == $groupb) && (false == $groupc) && (false == $groupd)) :?>
        group b multi end<br>
    <?php endif;?>


    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-c-first'):?>
                group c first - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>
    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-c'):?>
                group c - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>

    <?php if (( true == $groupa ) && (true == $groupb) && (true == $groupc) && ($groupd == false)) :?>
        group c multi end<br>
    <?php endif;?>

    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-d-first'):?>
                group d first - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>
    <?php foreach($duplicates as $postID) { ?>
        <?php $postData = get_post( $postID );?>
            <?php if(esc_html(get_the_category($postID)[0]->slug) == 'group-d'):?>
                group d - <?php print $postData->post_title;?><br>
            <?php endif;?>
    <?php } ?>

    <?php if (( true == $groupa ) && (true == $groupb) && (true == $groupc) && ($groupd == true)) :?>
        group d multi end<br>
    <?php endif;?>

<?php endif;?>

//the second loop. Also sets two columns
<?php $row_start = 1; while ( $query->have_posts() ) : $query->the_post();?>

    // if the category "first" is set to true, split posts into columns with most posts favoring the left. I.E. if the loop has ten posts, it is evenly split. If not, the split favors the right side.
    <?php if(true == $firstonly):?>
        <?php if(in_array( get_the_ID(), $duplicates ) ) continue; ?>
            <?php if($row_start % 2 != 0 && $row_start != ($sum_total = $wp_query->found_posts - count($duplicates))):?>
                <?php $left[] = get_the_ID();?>
            <?php else:?>
                <?php $right[] = get_the_ID();?>
            <?php endif;?>
    <?php else:?>
        <?php if(in_array( get_the_ID(), $duplicates ) ) continue; ?>
            <?php if($row_start % 2 != 0):?>
                <?php $left[] = get_the_ID();?>
            <?php else:?>
                <?php $right[] = get_the_ID();?>
            <?php endif;?>
    <?php endif;?>

// end the column, the loop, the query and reset the query.     
<?php ++$row_start; endwhile; wp_reset_postdata();?>

// the output of the second loop.   
<?php foreach($left as $postID) { ;?>
    <?php $postData = get_post( $postID );?>
    left - <?php print $postData->post_title;?><br>
<?php } ?>
<?php foreach($right as $postID) { ;?>
    <?php $postData = get_post( $postID );?>
    right - <?php print $postData->post_title;?><br>
<?php } ?>

Thanks everyone for the help! This is probably the most complex problem I've ever encountered. Thank you so much for the help!

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.