Forums Forums Search & Filter Pro Multiple forms on one page + search analytics

Viewing 6 posts - 11 through 16 (of 16 total)
  • Trevor
    #168274
    This reply has been marked as private.
    Anonymous
    #168440
    This reply has been marked as private.
    Ross Moderator
    #168826

    Hi Liam

    I had a look (and was surprised that you could add an orderby with random seed to the query object so easily)! You learn something new every day!

    Anyway, I tested the code you were using and it mostly seemed correct – but I had some trouble getting it working.

    I realised, in this scenario, using our filter sf_edit_query_args was the wrong filter to use, because it is called several times (once for the main query, and again, while generating our filters) – which probably meant your seed being continually reset, or reset 3 times in 1 page load.

    — As a side note, the whole purpose of this filter we use is so that any modification you do to the query, is also reflected in the filter counts…

    However, in this case, ordering the results will have no effect on the filter counts, so its not necessary and we can go ahead and use pre_get_posts.

    Using your code, and some I’ve found online, I think I’ve managed to successfully do this:

    
    session_start();
    add_filter( 'pre_get_posts', 'sf_sort_random_seed', 200, 2 );
    function sf_sort_random_seed( $query ) {
    
    	if( !is_admin() && $query->is_main_query() ) {
    			
    		//$query->set( 'posts_per_page', 1 ); // testing
    		
    		//grab the ID from the query_vars
    		$sfid = 0;
    		if(isset($query->query_vars['search_filter_id'])) {
    			$sfid = $query->query_vars['search_filter_id'];
    		}
    
    		if($sfid==27339||$sfid==27361) {
    
    			// Reset seed on load of initial archive page
    			$sf_paged = 0;
    			if(isset($_GET['sf_paged'])){
    				$sf_paged = $_GET['sf_paged'];
    			}
    
    			if( $sf_paged == 0 || $sf_paged == 1 ) {
    				if( isset( $_SESSION['seed'] ) ) {
    					unset( $_SESSION['seed'] );					
    				}
    			}
    
    			// Get seed from session variable if it exists
    			$seed = false;
    			if( isset( $_SESSION['seed'] ) ) {
    				$seed = $_SESSION['seed'];
    			}
    
    			// Set new seed if none exists
    			if ( ! $seed ) {
    				$seed = rand();
    				$_SESSION['seed'] = $seed;
    			}
    
    			// Inject the order into the query
    			$query->set( 'orderby', 'RAND(' . $seed . ')' );
    		
    		}
    	}
    	
    	return $query;
    }

    This seems to be working for me anyway! Just watchout when using sessions, I’ve heard many cases of them not working in WP, and needing to use transients instead.

    Let me know if it works!

    Thanks

    Anonymous
    #168910

    Thanks Ross!

    I had a feeling the supplied filter was not going to work. I tested your version of the function and was unable to get it working. I realised that I hadn’t yet attempted to do this with transients! I completely forgot about them, havent used them in years. My main problem was getting getting session/cookie data to work so this presented a new avenue to explore.

    I rewrote your function using transients and was immediately able to get it reading and writing properly. I was then able to debug why the function still wasn’t working and realised the injected orderby var was being ignored. I realised that pre_get_posts will have no effect on the posts order because the posts_orderby action will override it after that.

    So! I restructured the function that modifies the pre_get_posts query and use it to filter the posts_orderby variable after that. voila! I did some testing and so far its working on all fronts. This works with or without ajax and works with my original setup of having 2 forms on a single page for the same archive.

    Feel free to share with anyone that wants to preserve pagination with random ordering:

    function sf_pre_posts( $query ){
    	if( !is_admin() && $query->is_main_query() ) {	
    		$sfid = 0;
    		if(isset($query->query_vars['sfid'])) {
    			$sfid = $query->query_vars['sfid'];
    		}
    		if($sfid==27339||$sfid==27361) {
    			add_filter('posts_orderby', 'sf_order_random_seed');
    		}
        } else {
            remove_filter('posts_orderby', 'sf_order_random_seed');
        }
    }
    add_action( 'pre_get_posts', 'sf_pre_posts', 200, 2  );
    
    function sf_order_random_seed( $orderby ) {
    	// Reset seed on load of initial archive page
    	$sf_paged = 0;
    	if(isset($_GET['sf_paged'])){
    		$sf_paged = $_GET['sf_paged'];
    	}
    	// Detect first page of results
    	if( $sf_paged == 0 || $sf_paged == 1 ) {
    		if( get_transient( 'rand_trans' ) ) {
    			// delete transient if it exists
    			delete_transient( 'rand_trans' );
    		}
    	}
    	// Get seed from transient if it exists
    	$seed = false;
    	if( get_transient('rand_trans') ) {
    		$seed = get_transient( 'rand_trans' );
    	}
    	// Set new seed and transient if none exists
    	if ( ! $seed ) {
    		$seed = rand();
    		set_transient( 'rand_trans', $seed, 60*60*12 );
    	}
    	// Setup orderby statement
    	$orderby = 'RAND('.$seed.')';
    	return $orderby;
    }

    Thanks you both for the feedback and good tips, really appreciate it.

    Cheers,
    Josh.

    Ross Moderator
    #168982

    Hi Josh!

    It’s strange, I would have never thought putting the random(seed) in the query using ->set would work, and by the sounds of it, that’s why you went with the posts_orderby filter (which is also the method I found when googling).

    However, it actually seemed to worked fine for me, most odd.

    Thanks for sharing anyway – this is something I will likely include in an upcoming version of S&F.

    Best

    Ross Moderator
    #168999

    Hi Josh

    I’ve just thought of a problem with your logic.

    When saving $_SESSION variables, these are personalised to each visitor so would work as expected.

    However, the transient you are using is global – it has one name for every user. This means, when another user visits page 1 of results, your seed will be reset, causing problems for another visitor on page 2 etc.

    I can’t remember how exactly, but there is a way to use transients like sessions, so every visitor gets their own key generated – I think WooCommerce and others do something similar but I’m afraid I can’t think of how off the top of my head.

    Anyway thought I’d give you a headsup on that as it just popped into my head.

    Thanks

Viewing 6 posts - 11 through 16 (of 16 total)