6

I have a custom post type 'Property' which my users need to be able to search by meta data.

I have 3 search functions - 2 on the frontend 1 in the admin area - 2 of which are running as expected and one which doesn't seem to be filtering results at all.

I think there may be a problem with either my definition or usage of custom query_vars.

In my functions.php I have the following:

function add_query_vars($public_query_vars) {
    $public_query_vars[] = 'bedrooms';
    $public_query_vars[] = 'type';
    $public_query_vars[] = 'location';
    return $public_query_vars;
}
add_filter('query_vars', 'add_query_vars');

function meta_search_query($query) {

    $query_args_code = array(
      'posts_per_page' => 5,
      'post_type' => 'nc_property',
      'meta_key' => 'nc_code',
      'meta_value' => $query->query_vars['s'],
      'meta_compare' => 'LIKE'
    );


    $query_args_meta = array(
        'posts_per_page' => -1,
        'post_type' => 'nc_property',
        'meta_query' => array(
            'relation' => 'AND',
            array(
                'key' => 'nc_bedrooms',
                'value' => $query->query_vars['bedrooms'],
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'nc_type',
                'value' => $query->query_vars['type'],
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'nc_location',
                'value' => $query->query_vars['location'],
                'compare' => 'LIKE'
            )
        )
    );

    if (is_admin() && $query->is_search ) {
        query_posts($query_args_code);

    } elseif (!is_admin() && $query->is_search ) {
        if ($_REQUEST["which_form"] == 'meta_form') {
            query_posts($query_args_meta);

        } elseif ($_REQUEST["which_form"] == 'code_form'){
            query_posts($query_args_code);

        }
    }  
}
add_filter( 'pre_get_posts', 'meta_search_query');

Searching by the property code works no problem at all in both the frontend and backend however trying to filter results by the custom query vars - location, type and bedrooms - falls flat everytime.

An example query string which is created is as follows:

/property/?post_type=nc_property&which_form=meta_form&bedrooms=Two&type=Apartment&location=Bahceli

There is one property on the site which matches those details but WordPress returns all results each time.

Have I missed something?

EDIT: It turns out that because my search form for my meta queries was not using an element with 's' as its name the $query->is_search condition of my if statement was returning false, meaning my meta_query simply wasn't being called.

Kudos to fischi for spotting this for me! :D

5
  • Do the custom query vars get recognized by WordPress? If you var_dump them, do you get values for $query->query_vars?
    – fischi
    Commented Jan 28, 2014 at 16:10
  • Hmm the custom query vars are all returning NULL when I var dump them. Why would this be?
    – Jazibobs
    Commented Jan 28, 2014 at 16:16
  • Probably because you have a mix of pretty permalink and $_GET variables. Can you try inserting the $_GET data instead of $query->query_vars? Do not forget to sanitize it if you are going this way :)
    – fischi
    Commented Jan 28, 2014 at 16:18
  • using $_GET returns the vars as expected: array(3) { [0]=> string(3) "Two" [1]=> string(9) "Apartment" [2]=> string(7) "Bahceli" } do you think a straight swap for $_GET in my functions.php will solve the issue?
    – Jazibobs
    Commented Jan 28, 2014 at 16:29
  • Does this answer your question? Using get_posts with arguments found in meta keys
    – T.Todua
    Commented Jan 30, 2021 at 17:09

1 Answer 1

6

In this case, as you mix pretty permalinks with request parameters, I would use the $_GET variables in your query.

$query_args_meta = array(
    'posts_per_page' => -1,
    'post_type' => 'nc_property',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'nc_bedrooms',
            'value' => sanitize_text_field( $_GET['bedrooms'] ),
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'nc_type',
            'value' => sanitize_text_field( $_GET['type'] ),
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'nc_location',
            'value' => sanitize_text_field( $_GET['location'] ),
            'compare' => 'LIKE'
        )
    )
);

Be sure to use the proper sanitation, depending on your needs, or using a function that checks for whitelisted values of the $_GET data.

Also check your function of the conditionals - you just alter the query if it is a search request (using s as search parameter), or alter the if statement.

6
  • I have made the changes you recommended however the search results still do not appear to be filtered whatsoever even though I know the $_GET variables are being picked up correctly when I var_dump...
    – Jazibobs
    Commented Jan 28, 2014 at 16:38
  • Can you have a look at what query your WordPress runs? <?php echo $GLOBALS['wp_query']->request; ?>
    – fischi
    Commented Jan 28, 2014 at 16:42
  • The query is as follows SELECT SQL_CALC_FOUND_ROWS north_posts.ID FROM north_posts WHERE 1=1 AND north_posts.post_type = 'nc_property' AND (north_posts.post_status = 'publish' OR north_posts.post_status = 'private') ORDER BY north_posts.post_date DESC LIMIT 0, 10 so it seems that my meta query is just being ignored? :/
    – Jazibobs
    Commented Jan 28, 2014 at 16:45
  • 1
    ups, saw another thing - if you do not use the s parameter your condition if (!is_admin() && $query->is_search ) is not met, as WordPress does not know this is a search. Try changing that too.
    – fischi
    Commented Jan 28, 2014 at 17:03
  • You are a WordPress hero! Making one of the search fields have a name of 's' has solved the issue!
    – Jazibobs
    Commented Jan 28, 2014 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.