1

I created a post loader shortcode, that uses AJAX to load posts. Even though I can set the order and order_by query parameters, the order_by should be random. From what I've seen on the web, ajax load and random order aren't best pals, because of same post loading over and over.

So I've thought: I'll just put post id's in one of my elements (as a data attribute), update that on ajax as well, and use post__not_in to put those posts there, so the ajax load won't load them (already loaded ones).

Great, right? Well no. For some reason, if I specify the post_per_page parameter to be a certain number, it doesn't work. However, if I set it to -1 the loading works fine.

The code looks like this:

SHORTCODE

<?php
// Usage: [show_post_excerpts category="" title="" count="" order="ASC|DESC" orderby="" class=""]
function myslug_post_excerpts( $atts, $content ){
    extract(shortcode_atts(array(
        'category'  => '',
        'title'     => '',
        'count'     => '6',
        'order'     => '',
        'orderby'   => '',
        'class'     => '',
    ), $atts));

    $order_val = ( $order != '' ) ? $order : '';
    $order_by = ( $orderby != '' ) ? $orderby : '';

    $cat_obj = get_category_by_slug($category);
    $cat_id = $cat_obj->term_id;

    $query = array(
        'cat'            => $cat_id,
        'posts_per_page' => $count,
        'orderby'        => $order_by,
        'order'          => $order_val,
    );

    ?>
    <div class="recent_posts <?php echo $category. ' ' .$class; ?>">
        <div class="recent_posts_title"><?php echo $title; ?><div class="recent_post_loader" data-orderby="<?php echo $order_by; ?>" data-order="<?php echo $order_val; ?>" data-cat="<?php echo $cat_id; ?>" data-ppp="<?php echo $count; ?>"></div></div>
        <?php
        $myposts = new WP_Query( $query );

        if( $myposts->have_posts() ) : while( $myposts->have_posts() ) :  $myposts->the_post();

        $post_ids = wp_list_pluck( $myposts->posts, 'ID' );
        $post_ids_string = implode( ',', $post_ids );

        $post_thumb = has_post_thumbnail( get_the_ID() ) ? '' : 'no_thumbnail';
        ?>

        <div class="recent_post">
            <?php if(has_post_thumbnail( get_the_ID() )): ?>
            <div class="post_image">
                <?php echo get_the_post_thumbnail( get_the_ID() ); ?>
            </div>
            <?php endif; ?>
            <div class="post_info <?php echo $post_thumb; ?>">
                <a href="<?php the_permalink( get_the_ID() ); ?>" class="recent_post_title"><?php echo get_the_title( get_the_ID() ); ?></a>
                <div class="post_date"><?php echo get_the_date('d F Y, H:i',  get_the_ID() ); ?></div>
            </div>
        </div>

        <?php endwhile; endif;
        wp_reset_postdata(); ?>
        <div class="posts_ids" data-ids="<?php echo $post_ids_string; ?>"></div>
    </div>

    <?php
}
add_shortcode( 'show_post_excerpts', 'myslug_post_excerpts');

FUNCTION ON AJAX CALL

add_action( 'wp_ajax_myslug_add_recent_posts', 'myslug_add_recent_posts' );
add_action( 'wp_ajax_nopriv_myslug_add_recent_posts', 'myslug_add_recent_posts' );

function myslug_add_recent_posts(){

    $cat      = (isset($_POST['cat'])) ? $_POST['cat'] : '';
    $ppp      = (isset($_POST['ppp'])) ? $_POST['ppp'] : '';
    $order_by = (isset($_POST['order_by'])) ? $_POST['order_by'] : '';
    $order    = (isset($_POST['order'])) ? $_POST['order'] : '';
    $ids      = (isset($_POST['ids'])) ? $_POST['ids'] : '';
    $paged    = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 1;

    if (isset($ids) && $ids != '') {
        $not_in = explode(',', $ids);
    }


    $output = '';

    $recent_query = array(
        'cat'            => $cat,
        'paged'          => $paged,
        'posts_per_page' => -1,
        'orderby'        => $order_by,
        'order'          => $order,
        'post__not_in'   => $not_in,
    );

    $myposts = new WP_Query( $recent_query );

    if( $myposts->have_posts() ) : while( $myposts->have_posts() ) :  $myposts->the_post();

    $post_thumb = has_post_thumbnail( get_the_ID() ) ? '' : 'no_thumbnail';

    $output .= '<div class="recent_post" data-post_id="'.get_the_ID().'">';
    if(has_post_thumbnail( get_the_ID() )){
        $output .= '<div class="post_image">
                        '.get_the_post_thumbnail( get_the_ID() ).'
                    </div>';
    }
        $output .= '<div class="post_info '.$post_thumb.'">
                        <a href="'.get_the_permalink( get_the_ID() ).'" class="recent_post_title">'.get_the_title( get_the_ID() ).'</a>
                        <div class="post_date">'.get_the_date('d F Y, H:i',  get_the_ID() ).'</div>
                    </div>
                </div>';
    endwhile; endif;
    wp_reset_postdata();

    die($output);
}

AJAX CALL

var $recent_post_loader = $('.recent_post_loader');
var $container_recent;
var page_recent_number  = 1;
var recent_order_by,
    recent_order,
    cat_recent,
    recent_post_id,
    recent_ids,
    ppp_recent;

$(document).on('click', '.recent_post_loader', function () {
    var $this              = $(this);
    $container_recent      = $this.parents('.recent_posts');
    recent_order_by        = $this.data('orderby');
    recent_order           = $this.data('order');
    cat_recent             = $this.data('cat');
    ppp_recent             = $this.data('ppp');
    recent_ids             = $container_recent.find('.posts_ids').attr('data-ids');
    load_recent_posts();
});

function load_recent_posts() {
    if (!($recent_post_loader.hasClass('recent_posts_loading') || $recent_post_loader.hasClass('no_more_recent_posts'))) {
        page_recent_number++;
        var str = '&ppp=' + ppp_recent + '&cat=' + cat_recent + '&order_by=' + recent_order_by + '&order=' + recent_order + '&ids=' + recent_ids + '&pageNumber=' + page_recent_number + '&action=myslug_add_recent_posts';
        $.ajax({
            type: 'POST',
            dataType   : 'html',
            url: myslug_ajax_posts.ajaxurl,
            data: str,
            success: function (data) {
                var $data = $(data);
                if ($data.length) {
                    var $newElements = $data.css({ opacity: 0 });
                    $data.each(function(){
                        recent_post_id = $(this).data('post_id');
                        recent_ids += ','+recent_post_id;
                    });
                    $container_recent.append($newElements);
                    $container_recent.imagesLoaded(function () {
                        $newElements.animate({ opacity: 1 });
                    });
                    $recent_post_loader.removeClass('recent_posts_loading');
                } else {
                    $recent_post_loader.addClass('no_more_recent_posts');
                    $container_recent.append('<div class="recent_post"><p>' + myslug_ajax_posts.noposts + '</p></div>' );
                }
            },
            beforeSend : function () {
                $recent_post_loader.addClass('recent_posts_loading');
            },
            error : function (jqXHR, textStatus, errorThrown) {
                $recent_post_loader.html(jqXHR + ' :: ' + textStatus + ' :: ' + errorThrown);
            },
            complete : function () {
                $recent_post_loader.removeClass('recent_posts_loading');
                $container_recent.find('.posts_ids').attr('data-ids', '').attr('data-ids', recent_ids);
            }
        });
    }
    return false;
}

If I put $ppp instead of -1 in my function, I don't get any post when I click the loader.

The -1 isn't a good solution, because I could have 1000 posts in a category, and loading them all isn't a viable option. I'd like only to show, 6, or 3, or what ever number of posts I specify.

Why does this happen? If I remove post__not_in and let the random order happen, I get same posts loaded on click. I get the correct number of posts (say I have 8 posts, and 6 shown, on click the 2 posts will load), but sometimes they are duplicated, sometimes not. So this isn't working.

The 'workaround' with post__not_in should work (in theory).

Any idea as to why this happens?

  • setting paged seems a bit strange. If you're excluding previous posts and randomizing the remaining ones, don't you always want the first page of those results? – Milo Feb 3 '16 at 7:48
  • Well first I show posts from the 'first page'. Then I load the ones from the 'second page' and so on. At least that's my logic (I could be wrong). I mean, how else can I track what posts I already posted? – dingo_d Feb 3 '16 at 7:51
  • Omg I commented out the paged and it works O.o Can you please explain why is that? I guess my 'logic' was wrong this whole time :\ – dingo_d Feb 3 '16 at 7:53
  • if you're excluding the posts from the first page when you request the second page, there is no first page anymore in the context of that new query. what was on page 2 of the original query is now on page 1 of the new query. – Milo Feb 3 '16 at 7:57
  • Right, that makes sense. Thank you :) You can write it as an answer, so that I can accept it :) – dingo_d Feb 3 '16 at 8:03

Your Answer

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

Browse other questions tagged or ask your own question.