Search code examples
wordpressadvanced-custom-fields

Wordpress & ACF Filter posts by ACF value


I have filter the results like this and working: https://test.qualitybusinessawards.com/search?city=Chicago

If i want to filter like this City & Category is not working properly: https://test.qualitybusinessawards.com/search?city=Chicago&category=Dentist Here appear all Dentist but i want to appear only Dentist from Chicago.

I have created with this function:

 function my_pre_get_posts( $query ) {
    
    // do not modify queries in the admin
    if( is_admin() ) {
        
        return $query;
        
    }
    
    
    // only modify queries for 'event' post type
    if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'post' ) {
        
        // allow the url to alter the query
        $city = isset($_GET['city']);
        $category = isset($_GET['category']);

        if( $city )  {
            
            $query->set('meta_key', 'city');
            $query->set('meta_value', $_GET['city']);
            
        } 

        if( $category )  {
            
            $query->set('meta_key', 'category', '=');
            $query->set('meta_value', $_GET['category']);
            
        } 
        
        
    }
    
    
    // return
    return $query;

}

add_action('pre_get_posts', 'my_pre_get_posts');

I have try to make lot of changes in this code but is not working....


Solution

  • This is not tested.

    I think your problem is that you are trying to set multiple meta queries, but you are not nesting each meta query inside the meta_query array.

    You are currently just setting these meta queries in the main the query args and hoping for the best.

    Nope, aint guna work my man. You need to imagine you are writing a WP_Query args array with Custom Field (post meta) Parameters

    Skip to Display posts from several custom fields example (in link above).

    The above Wordpress docs example shows correct usage of building your args array for WP_Query, see below...

    $args = array(
        'post_type'  => 'product',
        'meta_query' => array(
            array(
                'key'     => 'color',
                'value'   => 'blue',
                'compare' => 'NOT LIKE',
            ),
            array(
                'key' => 'price',
                'value'   => array( 20, 100 ),
                'type'    => 'numeric',
                'compare' => 'BETWEEN',
            ),
        ),
    );
    $query = new WP_Query( $args );
    

    So lets remove all the meta_query params from the above query $args array, and lets pretend the below args is your my_pre_get_posts passed $query parameter...

    $query = array(
        'post_type'  => 'product'
    );
    

    OK, all is well, until you try and $query->set your meta values in your current question code. If $city and $category are true... here is the args you will be left with...

    $query = array(
        'post_type' => 'product',
        'meta_key' => 'city',
        'meta_value', 'Chicago',
        'meta_key' => 'category',
        'meta_value', 'Dentist'
    );
    

    $query does not look good, right! This will bomb out as you are trying to use a single meta query twice in your query args!

    You need to combine multiple meta queries into one array like this...

    $query = array(
        'post_type' => 'product',
        'meta_query' => array(
            array(
                'key'     => 'city',
                'value'   => 'Chicago',
                'compare' => '='
            ),
            array(
                'key' => 'category',
                'value'   => 'Dentist',
                'compare' => '='
            ),
        )
    );
    

    So in order to fix your question code is to pre build a $meta_query array variable prior to using $query->set()...

    See your original code below, modified and fixed in example code below... (not tested)

    function my_pre_get_posts( $query ) {
        
        // do not modify queries in the admin
        if( is_admin() ) {
            
            return $query;
            
        }
        
        // only modify queries for 'event' post type
        if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'post' ) {
            
            // check url params using gets
            $city = isset($_GET['city']);
            $category = isset($_GET['category']);
    
            // set empty meta query array var but get any existing meta query params
            $meta_query = (array)$query->get('meta_query');
    
            // if city url param is set
            if($city) {
                
                // add city meta query array to main meta_query array
                $meta_query[] = [
                    'key'     => 'city',
                    'value'   => $city,
                    'compare' => '='
                ];
                
            } 
    
            // if category url param is set
            if($category)  {
                
                // add category meta query array to main meta_query array
                $meta_query[] = [
                    'key'     => 'category',
                    'value'   => $category,
                    'compare' => '='
                ];
                
            } 
    
            // then the magic happens here by setting all the above `$meta_query` array using `set()`
            $query->set('meta_query', $meta_query);
            
        }
        
        // boom then return...
        return $query;
    
    }
    
    // pre get post action function call
    add_action('pre_get_posts', 'my_pre_get_posts');