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.

Trying to build a search that not only searches the defaults (title, content etc) but also a specific custom field.

My current query:

$args = array(
  'post_type' => 'post',
  's' => $query,
  'meta_query' => array(
     array(
       'key' => 'speel',
       'value' => $query,
       'compare' => 'LIKE'
     )
   )
);

$search = new WP_Query( $args )
...

This returns posts which match both the search query AND the meta query, but I would also like it to also return posts where it simply matches either one of them.

Any ideas?

share|improve this question
    
What you are wanting to do isn't possible using just one search query. You would need to run both queries separately and then merge them together. This has been described at this other answer. It should give you a hand with how to do it. wordpress.stackexchange.com/questions/55519/… –  Nick Perkins Jan 8 '13 at 4:31
add comment

3 Answers 3

up vote 1 down vote accepted

As per Nick Perkins' suggestion, I had to merge two queries like so:

$q1 = get_posts(array(
        'post_type' => 'post',
        's' => $query
));

$q2 = get_posts(array(
        'post_type' => 'post',
        'meta_query' => array(
            array(
               'key' => 'speel',
               'value' => $query,
               'compare' => 'LIKE'
            )
         )
));

$merged = array_merge( $q1, $q2 );

$post_ids = array();
foreach( $merged as $item ) {
    $post_ids[] = $item->ID;
}

$unique = array_unique($post_ids);

$posts = get_posts(array(
    'post_type' => 'posts',
    'post__in' => $unique,
    'post_status' => 'publish',
    'posts_per_page' => -1
));

if( $posts ) : foreach( $posts as $post ) :
     setup_postdata($post);

     // now use standard loop functions like the_title() etc.     

enforeach; endif;
share|improve this answer
add comment

Well its kind of a hack but it works. You need to add posts_clauses filter. This filter function check for the any of the query word exists in the custom field "speel" and the remaining query stays intact.

function custom_search_where($pieces) {

    // filter for your query
    if (is_search() && !is_admin()) {

        global $wpdb;

        $keywords = explode(' ', get_query_var('s'));
        $query = "";
        foreach ($keywords as $word) {

            // skip possible adverbs and numbers
            if (is_numeric($word) || strlen($word) <= 2) 
                continue;

            $query .= "((mypm1.meta_key = 'speel')";
            $query .= " AND (mypm1.meta_value  LIKE '%{$word}%')) OR ";
        }

        if (!empty($query)) {
            // add to where clause
            $pieces['where'] = str_replace("(((wp_posts.post_title LIKE '%", "( {$query} ((wp_posts.post_title LIKE '%", $pieces['where']);

            $pieces['join'] = $pieces['join'] . " INNER JOIN {$wpdb->postmeta} AS mypm1 ON ({$wpdb->posts}.ID = mypm1.post_id)";
        }
    }
    return ($pieces);
}
add_filter('posts_clauses', 'custom_search_where', 20, 1);
share|improve this answer
add comment

A lot of code can be reduced by using a modified version of this answer.

$q1 = new WP_Query( array(
    'post_type' => 'post',
    'posts_per_page' => -1,
    's' => $query
));

$q2 = new WP_Query( array(
    'post_type' => 'post',
    'posts_per_page' => -1,
    'meta_query' => array(
        array(
           'key' => 'speel',
           'value' => $query,
           'compare' => 'LIKE'
        )
     )
));

$result = new WP_Query();
$result->posts = array_unique( array_merge( $q1->posts, $q2->posts ), SORT_REGULAR );
$result->post_count = count( count( $result->posts ) );
share|improve this answer
add comment

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.