Support

Account

Home Forums General Issues 2 pre_get_posts functions to filter by custom fields

Solved

2 pre_get_posts functions to filter by custom fields

  • I have an “Actions” page (an archive for a custom post type called Actions), which is an equivalent to “events”:

    I used this tutorial to filter them with custom fields: ville (city), action (type of event) and date and it works perfectly.

    Then I created another function to filter by “date range”: past, future actions. And it also works. But posts don’t get filtered, they “accumulate”. When I select “Past actions” and a “City”, it shows me [ALL past actions from all cities + ALL actions (past and future) in the selected city] instead of [only past actions from that city].

    EDIT: I found a solution, I put the code as an answer to this post.

    // array of filters (field key => field name)
            $GLOBALS['my_query_filters'] = array( 
                'action'	=> 'action', 
                'ville'	    => 'ville', 
                'date'	    => 'date'
            );
    
    add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
    
    function my_pre_get_posts( $query ) {
    	
    	// bail early if is in admin
    	if( is_admin() ) return;
        
    	// bail early if not main query
    	// - allows custom code / plugins to continue working
    	if( !$query->is_main_query() ) return;
    
        if( ! is_post_type_archive( 'actions' ) ) return;
        
            // FUTURE/PAST/ALL filters
        if( isset($_GET['range']) ) {
            
        $range = explode(',', $_GET['range']);
    
          if($range != "toutes") {
              
              // Select what kind of compare you need
              if($range == "past") {
                $comparer = '<';
              } else if($range == "future") {
                $comparer = '<';
              }
            
            // If you need to filter by date add this to meta_query array
            $meta_query[] = array(
                'key'     => 'date',
                'value'   => date("Ymd"),
                'compare' => $comparer,
                );
              }
           }
     
        // CITY/TYPE/DATE filters
        // loop over filters
    	foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
    		
    		// continue if not found in url
    		if( empty($_GET[ $name ]) ) { continue; }
    		
    		// get the value for this filter
    		// eg: http://www.website.com/events?city=melbourne,sydney
    		$value = explode(',', $_GET[ $name ]);
                
            // append meta query
        	$meta_query[] = array(
                'key'		=> $name,
                'value'		=> $value,
                'compare'	=> 'IN',  
            );
    	}
    
    	// update meta query
    	$query->set('meta_query', $meta_query);
        
        $query->set( 'meta_key', 'date' );
        $query->set( 'orderby', array( 'date' => 'DESC' ) );
        $query->set('posts_per_page', '20');
        
    }
    
    
  • Here’s the working code, in case it can help others.
    The main problem of the previous one was that I set the queries multiple times, while here I append to it using $meta_query[] =

    <?php
    // array of filters (field key => field name)
            $GLOBALS['my_query_filters'] = array( 
                'action'	=> 'action', 
                'ville'	    => 'ville', 
                'date'	    => 'date'
            );
    
    add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
    
    function my_pre_get_posts( $query ) {
    	
    	// bail early if is in admin
    	if( is_admin() ) return;
    	
    	// bail early if not main query
    	// - allows custom code / plugins to continue working
    	if( !$query->is_main_query() ) return;
    
        if( ! is_post_type_archive( 'actions' ) ) return;
        
        
         // CITY/TYPE/DATE filters
        // loop over filters
    	foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
    		
    		// continue if not found in url
    		if( empty($_GET[ $name ]) ) { continue; }
    		
    		// get the value for this filter
    		// eg: http://www.website.com/events?city=melbourne,sydney
    		$value = explode(',', $_GET[ $name ]);
                
            // append meta query
        	$meta_query[] = array(
                'key'		=> $name,
                'value'		=> $value,
                'compare'	=> 'IN',  
            );
    	}
        
            // FUTURE/PAST/ALL filters
        if( isset($_GET['range']) ) {
            
        $range = $_GET['range'];
    
          if($range != "toutes") {
              
              // Select what kind of compare you need
              if($range == "past") {
                $comparer = '<';
              } else if($range == "future") {
                $comparer = '>=';
              }
            
            // If you need to filter by date add this to meta_query array
            $meta_query[] = array(
                'key'     => 'date',
                'value'   => date("Ymd"),
                'compare' => $comparer,
                );
              }
           }
        
       
        
    	// update meta query
    	$query->set('meta_query', $meta_query);
        
        $query->set( 'meta_key', 'date' );
        $query->set( 'orderby', array( 'date' => 'DESC' ) );
        $query->set('posts_per_page', '20');
        
    }
    
    ?>
  • Hi,

    I have created a custom post type on my website – event – and am trying to work out how to filter category pages for events so that only current/future event posts appear on the category pages (I have an ACF datetime field for events). Your post is the closest I have seen to a possible solution, as I think I need to use pre_get_posts but am in over my head a bit. Am I right in thinking I could alter what you have done here a bit to get the results I need?

    Thanks

    John

  • Hi John,

    I think so. I also have a custom post type (“actions”) so it should work for you.

    Cheers

  • I just want to thank you because your code helped me a lot! Best regards.

  • You’re welcome 🙂

Viewing 6 posts - 1 through 6 (of 6 total)

The topic ‘2 pre_get_posts functions to filter by custom fields’ is closed to new replies.