1

I'm trying to add custom fields to my search so that it can be refined by meta values. Currently I have added some select lists to my normal search:

<form role="search" action="<?php echo site_url('/'); ?>" method="get" id="searchform">
    <input type="hidden" name="s" value="carcpt" /> <!-- // hidden 'products' value -->

    <select name="price">
        <option value="">Nothing</option>
        <option value="500.00">500.00</option>
        <option value="100.00">100.00</option>
        <option value="50.00">50.00</option>
    </select>

    <select name="year">
        <option value="">Nothing</option>
        <option value="2011">2011</option>
        <option value="2007">2007</option>
        <option value="1991">1991</option>
    </select>

    <input type="submit" alt="Search" value="Search" />
</form>

and at the top of my search.php I have this conditional:

$q = get_search_query();
if($q = 'carcpt'){

    $price = $_GET['price'];
    $year = $_GET['year'];

    $search = new WP_Query(
        array(
            'post_type' => 'carcpt',
            'meta_query' => array(
                array(
                    'key' => '_price',
                    'value' => $price
                ),
                array(
                    'key' => '_year',
                    'value' => $year
                )
            )
        )
    );
}

That's the scenario - I have 2 questions:

1) This seems like a very 'hacky' way to add and refine my search results by custom fields - is there a better / more widely accepted way to do this?

2) The problem with the query above is that if the user does not enter a price or year - it will run the query and return only post with empty price/year meta. In my query is there a way to determine if a meta is empty and modify my query accordingly - not including a switch?

  • Be careful when using straight $_GET because those, if not escaped, can actually run malicious code. Ensure that you run something like: $p = (string) $_GET['price']; then use $p in your query. – Chad Nov 26 '15 at 16:31
  • @chad $_GET values are already in string format by default and some of the WordPress functions like WP_Query run through prepare() statements which make sure the string can be safely inserted or queried through the database. There's nothing that could be put into $_GET['price'] that would bring down the system or cause a vulnerability, only a query that returns no results. You can also read into PHP: PDO::prepare. – Howdy_McGee Nov 26 '15 at 16:58
3

1) I think that your solution is perfectly acceptable in terms of the "right way" - post meta is intended for searching. Doesn't seem hacky to me.

2) What you should do is build the meta_query separately:

$meta_query = array();

if( !empty( $_GET['price'] ) ) {
    $meta_query[] = array( 'key' => '_price', 'value' => $_GET['price'] );
}
if( !empty( $_GET['year'] ) ) {
    $meta_query[] = array( 'key' => '_year', 'value' => $_GET['year'] );
}

$search = new WP_Query( array(
    'post_type' => 'carcpt',
    'meta_query' => $meta_query
) );

This way you're only querying on meta keys that have a supplied, non-empty value.

I would like to point out that modification of query variables is better done in the pre_get_posts action, otherwise, as in this instance two queries will be executed: one for the search of 'carcpt', and then the second query for the 'carcpt' post type and meta query.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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