3

I need that the main page of my site have 3 columns: - The first having the 5 most viewed posts; - The second with the next 5 most viewed posts; - The third with the most recent posts.

I don't want the posts to be never repeated in the same column or another column, so I'm using wp_query to get the posts I want, in the number I want. Here's what happens when I load the second page, either using simple pagination or infinite scroll:

  • The first loop loads the 5-10 most viewed posts, which was already displayed on the first run of the second loop;
  • The second loop loads next 5 most viewed posts, which some has already been loaded on the third loop when it ran the first time;
  • The third loop loads the most recent posts and which wasn't been loaded on the first or second loops.

While I still loading the next pages, the loops loads the respective posts until I get any posts on the third loop, then have no posts in the second loop, and have all posts loaded into the first loop.

Here's the code I'm using:

<div id="content">

<div class="recentColumn">
<div class="columnContent">

<?

$hotArgs =  array(
    'post__not_in' => $loaded,
    'meta_key' => 'wpb_post_views_count', // Pega o número de visitas do post.
    'orderby' => 'meta_value_num', // Ordena do mais visitado para o menos visitado.
    'posts_per_page' => '2',
    'paged' => $paged
    );
$hot = new WP_Query( $hotArgs );


if ($hot->have_posts()) : while ($hot->have_posts()) : $hot->the_post();
$loaded[] = $post->ID;
?>

<div class="articleContent">
<article class="recent" role="article">

    <a href="<?php the_permalink();?>" title="<?php the_title();?>"><?php the_category();?>

    <header>
    <h1><a href="<?php the_permalink(); ?>" title="<?php the_title();?>"><?php the_title(); ?></a></h1>
    <?php the_excerpt(); ?>
    </header>

</article>
</div>

<?php endwhile; endif; ?>

</div>
</div>




<div class="popularColumn">
<div class="columnContent">

<?
$nextArgs =  array(
    'post__not_in' => $loaded,
    'meta_key' => 'wpb_post_views_count', // Pega o número de visitas do post.
    'orderby' => 'meta_value_num', // Ordena do mais visitado para o menos visitado.
    'posts_per_page' => '3',
    'paged' => $paged
    );
 $next = new WP_Query( $nextArgs );

if ($next->have_posts()) : while ($next->have_posts()) : $next->the_post();
$loaded[] = $post->ID; 
?>

<div class="articleContent">
<article class="popular" role="article">
        <a href="<?php the_permalink();?>" title="<?php the_title();?>"><?php the_category();?>

        <header>
        <h1><a href="<?php the_permalink(); ?>" title="<?php the_title();?>"><?php the_title(); ?></a></h1>
        </header>

</article>
</div>

<?php endwhile; endif; ?>

</div>
</div> 



<div class="randomColumn">
<div class="columnContent">

<?  
$recentsArgs =  array(
    'post__not_in' => $loaded,
    'posts_per_page' => '3',
    'paged' => $paged
    );
 $recents = new WP_Query( $recentsArgs );

if ($recents->have_posts()) : while ($recents->have_posts()) : $recents->the_post();
$loaded[] = $post->ID;
?>


<div class="articleContent">
<article class="random" role="article">
        <header>
        <h1><a href="<?php the_permalink(); ?>" title="<?php the_title();?>"><?php the_title(); ?></a></h1>
        </header>

</article>
</div>

<?php endwhile; endif; ?>

</div>
</div>

I think that the solution could be use a php session or variable that stores the id of the posts that have been already loaded, and in the loops check if the posts have been or not loaded before it continues. I tried to make this but it didn't work. I have too little skills on php, and maybe someone could have a better idea in how to make it work.

I appreciate any help. Thanks.

1

This might not solve your problem, but it will help you in future to create custom queries. Paginating more than one query can get extremely tricky. By default the build in pagination in Wordpress don't have this logic to paginate multiple queries. You will have to run multiple queries and merge them in some way.

OK, now to what I would like to point out. You should have a look at WP_Query in the codex to see how to properly create a custom query. Your problem here is that you are running three custom queries without resetting any of them. This will break any other query that follows the previous one

It is of utmost importance to reset every custom query that you create. You HAVE TO do that. You can do this by just calling wp_reset_postdata(); after each query to restore the $post variable. Look at the examples in the links provided

0

You could recreate the $loaded array from the database:

$hot_ppp = 3;
$next_ppp = 3;
$recents_ppp = 3;

if ( $paged > 1 ) {
    $prev_hot_next_loaded = $wpdb->get_col( $wpdb->prepare(
        'SELECT ID FROM ' . $wpdb->posts . ' p JOIN ' . $wpdb->postmeta . ' pm ON pm.post_id = p.ID AND pm.meta_key = %s'
        . ' WHERE p.post_type = %s AND p.post_status = %s ORDER BY pm.meta_value+0 DESC LIMIT %d',
        'wpb_post_views_count', 'post', 'publish', ( $hot_ppp + $next_ppp ) * ( $paged - 1 )
    ) );
    $prev_recents_loaded = $wpdb->get_col( $wpdb->prepare(
        'SELECT ID FROM ' . $wpdb->posts . ' WHERE ID NOT IN (' . implode(',', $prev_hot_next_loaded ) . ')'
        . ' AND post_type = %s AND post_status = %s ORDER BY post_date DESC LIMIT %d',
        'post', 'publish', $recents_ppp * ( $paged - 1 )
    ) );

    $loaded = $prev_hot_next_loaded + $prev_recents_loaded;
}

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.