Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm building a custom search form with keywords and drop down lists (categories, date, and country (have a separate plugin for this)).

In the searchform.php I have the input field and then select>option tags.

<!-- searchform.php (form) -->

<form action="/" method="get">

        <input type="text" name="s" id="search" value="<?php the_search_query(); ?>" />

        <select name="category">

            <select name="country">

              <option value=""></option>

              <option value="UK">UK</option>

              <option value="USA">USA</option>

              <option value="Brazil">Brazil</option>

              <option value="Poland">Poland</option>

              <option value="Canada">Canada</option>

            </select>

            <select name="year">

              <option value=""></option>

              <option value="2012">2012</option>

              <option value="2011">2011</option>

              <option value="2010">2010</option>

            </select>   

</form>



<?php

// search.php (results)

$args = array(

        's' => $_GET['s'],      

        'country' => $_GET['country'],

        'year' => $_GET['year']

);



$the_query = new WP_Query( $args );



if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>

        // Do Stuff

        <h3 class="search-title"><?php country_tag($post->ID); ?><a href="#" data-siteurl="<?php bloginfo('url'); ?>" rel="<?php the_ID(); ?>" title="<?php the_title_attribute(); ?>" class="search-post-title"><?php the_title(); ?></a></h3>



<?php 

endwhile;

endif;

?>

Problem: Currently if I leave the selects empty it sends them as empty strings in the get url (?s=keyword&country=&year=). This means that nothing will be found in the search. (I am guessing because its saying 'find matching posts with 'keyword' AND an empty string). So I want ?s=keyword to be passed if others are unused.

Perhaps I've setup the code wrong, likely as I've just started playing around with WP_Query.

share|improve this question
add comment

1 Answer

up vote 0 down vote accepted

That's certainly something you must solve on the server side, only omitting the arguments in URL would cause errors when accessing the non-existent keys in the $_GET array.

You should build your arguments array dynamically based on whether the values are set ot not.

Example:

$args = array();

foreach(array('s', 'country', 'year') as $key)
{
    // if key is available and not empty, include argument in the query
    if(isset($_GET[$key]) && trim($_GET[$key]) !== '')
    {
        $args[$key] = $_GET[$key];
    }
}

// 's' is neccessary for a search query, so only continue if it's available
if(isset($args['s']))
{
    $the_query = new WP_Query($args);
    ...
}

Update:

After figuring out what this country plugin is, I had a look at it. It manipulates the query, but it only checks whether the country key is present, not if it's empty, and it does this check on the global query object, so even if there is no country in your custom query, it will be present in the global query object because the plugin added the country key to the list of variables that will be fetched automatically (in case you didn't knew, WordPress will automatically query the posts for you). You may want to contact the plugin author and tell him about the problem so that he fixes it, until then, here's a quick and dirty fix for the current version:

// Hooks...
add_filter('posts_join', 'country_search_join', 10, 2);
add_filter('posts_where', 'country_search_where', 10, 2);
add_filter('posts_groupby', 'country_search_groupby', 10, 2);
add_filter('query_vars', 'country_queryvars');
add_action('init', 'country_flush_rewrite_rules');
add_action('generate_rewrite_rules', 'country_add_rewrite_rules');
add_action('plugins_loaded', 'country_widget_init');
add_action('admin_menu', 'manage_countries_menu');


// Join clause for the META table if a country is queried.
function country_search_join($join, &$wp_query)
{
    global $wpdb;

    if(isset($wp_query->query_vars['country']) && trim($wp_query->query_vars['country']) !== '') {
        $join .= " left join $wpdb->postmeta on $wpdb->posts.ID = $wpdb->postmeta.post_id ";
    }
    return $join;
}


// Add a where clause if a country is queried.
function country_search_where($where, &$wp_query)
{
    global $wpdb;

    if(isset($wp_query->query_vars['country']) && trim($wp_query->query_vars['country']) !== '') {
        $where = $where . " and {$wpdb->postmeta}.meta_key = 'Country' and {$wpdb->postmeta}.meta_value = '" . $wp_query->query_vars['country'] . "' ";
    }
    return $where;
}


// Add a group by clause if a country is queried to make sure posts are only returned once.
function country_search_groupby($groupby, &$wp_query)
{
    global $wpdb;

    if(!isset($wp_query->query_vars['country']) || trim($wp_query->query_vars['country']) === '') {
        return $groupby;
    }

    // Group on post ID
    $mygroupby = "{$wpdb->posts}.ID";

    // Is this group by already there?
    if(preg_match( "/$mygroupby/", $groupby)) {
        return $groupby;
    }

    // Is the group by empty?
    if(!strlen(trim($groupby))) {
        return $mygroupby;
    }

    // Append new group by clause.
    return $groupby . ", " . $mygroupby;
}

Now that i understand what exactly the plugin is doing there, i'd recommend not using a custom query, the query made by WordPress should be fine, ie something like this should do it:

<?php while ( have_posts() ) : the_post(); ?>

    <h3 class="search-title"><?php country_tag($post->ID); ?><a href="#" data-siteurl="<?php bloginfo('url'); ?>" rel="<?php the_ID(); ?>" title="<?php the_title_attribute(); ?>" class="search-post-title"><?php the_title(); ?></a></h3>

<?php endwhile; ?>
share|improve this answer
    
Thanks for getting back to me, I had been trying out all the if else statements but I retracted since it was so messy. Your solution is much cleaner. I have a print_r($args) and it previously showed empty array items. Your conditional has removed these from the print_r showing only s => keyword but still no results show. NOTE: if I remove the empty parameters from URL the page displays results. Any further thoughts? –  Graeme Oct 11 '12 at 11:03
    
Well, the problem could be anywhere, I've just did a quick test and it works fine for me. Have a look at $the_query->request to make sure the generated query is valid and that it will match anything at all. –  ndm Oct 11 '12 at 13:02
    
Odd. It wasn't working before. Thanks, that has certainly got me well on the right track! –  Graeme Oct 11 '12 at 13:16
    
Hi, still having problems with this again. When searching without select a country and only a keyword I get no results ?s=a&country=. But if i remove the country manually from the url it pulls results ?s=a. Why is this? It's really stumped me. I need to allow for people who do not want to refine their search. –  Graeme Oct 15 '12 at 16:09
    
It works fine for me with all possible key combinations, however i don't know your country plugin, there's a good chance that it manipulates the query and doesn't do so correctly, so as I recommended before, please have a look at $the_query->request to check if and what exactly is wrong with the generated query. Also check if the plugin is actually hooking in the query process anywhere. –  ndm Oct 15 '12 at 16:56
show 7 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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