• Hi

    This is a bit of a mish mash problem, so am posting here, instead of in the root.

    I am using a theme on my website “Smoothie – https://themeforest.net/item/smoothie-retina-responsive-wordpress-blog-theme/7030059/comments” which uses masonry to display posts. As far as I can tell, the theme has been abandoned by the developer.

    I have tried using several plugins to hide specific posts from the homepage (simply exclude, WP Hide Post etc). The plugins work great, but when I click the “Load More” link, to load the next 10 posts, the last post is duplicated at the beginning of the next 10 posts.

    If I hide 1 post, then the last post of the first 10 posts displayed is duplicated.
    or..
    If I hide 2 posts, then the last 2 posts of the first 10 posts displayed are duplicated.

    Is there anything I can add to the loop to check for duplicates? or how many posts were initially displayed?

    I have hidden 1 post on my test site, you can see the “Logo & Character Designs” post duplicating as a result when you click “Load More” here: https://dm2.electriccheese.co.uk/

    Many thanks

    Mr M

Viewing 4 replies - 1 through 4 (of 4 total)
  • Moderator bcworkz

    (@bcworkz)

    Any hide post plugin would naturally assume normal pagination and take measures to adjust queries to account for hidden posts. They could not possibly do the same for lazy loading scripts since there is no standard way that such scripts are implemented.

    Your lazy load script needs to be modified to add the hidden post count to the offset into the query for which posts to get next.

    Better yet would be to exclude the hidden posts from the main query to begin with so that the offset count need not be adjusted. This can be done through the ‘pre_get_posts’ action. The specifics of how that is done would depend on how the posts are designated as hidden.

    Thread Starter misterm2015

    (@misterm2015)

    Thanks for the reply bcworkz

    I did try using pre_get_posts just after posting this, but found myself going down the wrong track, excluding the post ID, which didn’t work, but did work with the cat ID, thinking I could add the excluded posts to their own additional category, then exclude that, but still produced duplicates.

    add_action( 'pre_get_posts', 'rc_modify_query_exclude_category' );
    function rc_modify_query_exclude_category( $query ) {
        if ( ! is_admin() && $query->is_main_query() && ! $query->get( 'cat' ) ) {
            $query->set( 'cat', '-49' );
        }
    }

    So, I’ve managed to exclude without the plugin, but still in the same position of not knowing how to handle the post counts :/

    I guess the added complication is that each new set of posts displayed will have different numbers of posts hidden. :/

    I’ve seen multiple loops used, but my PHP is only very slight, so is all above my head.

    Thread Starter misterm2015

    (@misterm2015)

    Hmmm, I undid what I did above, as it was pretty pointless.

    I tried to display how many posts were being displayed using count($posts), which always came out as 10, which is what I set in the reading prefs.

    The theme generated the first 10 posts in the index.php file, while the following posts loaded are generated in the functions file. Is this normal?

    index

    <?php
    						global $more; $more = 0;
    					?>
    					<?php if (have_posts()) : while ( have_posts() ) : the_post(); ?>
    					<div class="masonr">
    						<div <?php post_class('post'); ?>>
    							<!-- uses the post format -->
    							<?php
                                    if(!get_post_format()) {
                                        get_template_part('format', 'standard-small');
                                    } else {
                                        $format = get_post_format();
                                        if ($format == 'image') {get_template_part('format', 'image-small');}
                                        else if ($format == 'gallery') {get_template_part('format', 'gallery-small');}
                                        else {get_template_part('format', $format);}
                                    }
    							?>
    						</div><!-- post-->
    					</div>
    					<?php endwhile; ?>

    functions

    //-----------------------------------  // Load More AJAX Call //-----------------------------------  //
    if(!function_exists('cr_load_more')){
    	add_action('wp_ajax_cr_load_more', 'cr_load_more');
    	add_action('wp_ajax_nopriv_cr_load_more', 'cr_load_more');
    	function cr_load_more(){
    		if(!wp_verify_nonce($_POST['nonce'], 'cr_ajax')) die('Invalid nonce');
    		if( !is_numeric($_POST['page']) || $_POST['page']<0 ) die('Invalid page');
    
    		$args = '';
    		if(isset($_POST['archive']) && $_POST['archive']){
    			$args = $_POST['archive'] .'&';
    		}
    		$args .= 'post_status=publish&posts_per_page='. get_option('posts_per_page') .'&paged='. $_POST['page'];
    
    		if(isset($_POST['archive']) && $_POST['archive'] && strlen(strstr($_POST['archive'],'post-format'))>0){
    			$args = array(
    				'post_status' => 'publish',
    				'tax_query' => array(
    					array(
    						'taxonomy' => 'post_format',
    						'field' => 'slug',
    						'terms' => $_POST['archive']
    					)
    				),
    				'posts_per_page' => get_option('posts_per_page'),
    				'paged' => $_POST['page']
    			);
    		}
    
    		ob_start();
    		$query = new WP_Query($args);
    		while( $query->have_posts() ){ $query->the_post();
    		?>
    
    		<div class="masonr">	
    
    					<div <?php post_class('post'); ?>>
    		<?php
                if(!get_post_format()) {
                    get_template_part('format', 'standard-small');
                } else {
                $format = get_post_format();
                if ($format == 'image') {get_template_part('format', 'image-small');}
                else if ($format == 'gallery') {get_template_part('format', 'gallery-small');}
                else {get_template_part('format', $format);}
                }
    		?>
    			</div><!-- post-->
    				</div>
    		<?php
    		}
    		wp_reset_postdata();
    		$content = ob_get_contents();
    		ob_end_clean();
    		echo json_encode(
    			array(
    				'pages' => $query->max_num_pages,
    				'content' => $content
    			)
    		);
    		exit;
    	}
    }
    ?>

    Moderator bcworkz

    (@bcworkz)

    Yes, that’s right, sort of. The initial page of posts is loaded by the main query, which index.php displays. The functions.php script then requests more posts and adds them to the same page already displayed in the browser.

    WP pagination is normally handled by ‘posts_per_page’ and ‘paged’. You need to adjust for hidden posts by using the ‘offset’ argument, which overrides ‘paged’ and breaks the normal pagination. More info at Making Custom Queries using Offset and Pagination.

    You need to manage an array of posts to exclude in each query. The size of this array after the previous query is used to adjust the offset into the posts returned for the current query.

    For example: The first page has 10 posts plus 2 hidden. The IDs of the hidden posts are pushed into an exclusion array. On the next query for more posts, we would normally offset 10 so that the 11th post is the next one returned along with 9 more for another 10 posts. But the size of the exclusion array is 2, so our offset is actually 12 so that there are no duplicate posts. The query actually starts on the 13th post.

    The same logic is re-applied for every request for more posts. ‘pre_get_posts’ is the right place to do this, but the correct query vars need to be set using the correct logic.

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Masonry posts duplicating when hiding posts’ is closed to new replies.