WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have the followign code in my functions.php file

function __adapted_search_function($search, $query) {
  if(is_admin() || !$query->is_main_query() || !$query->is_search)
    return; //determine if we are modifying the right query

  global $wpdb;
  $search_term = $query->get('s');
  $search = ' AND (';

  //point 1
  $search .= "($wpdb->posts.post_title LIKE '%$search_term%')";

  //need to add an OR between search conditions
  $search .= " OR ";

  //point 2
  $search .= "($wpdb->posts.post_excerpt LIKE '%$search_term%')";

  //need to add an OR between search conditions
  $search .= " OR ";

  //point 3
  $search .= "($wpdb->postmeta.meta_key = 'mcb-product' AND $wpdb->postmeta.meta_value LIKE '%$search_term%')";

  //add the filter to join, sql will error out without joining the tables to the query
  add_filter('posts_join', '__custom_join_tables');   

  return $search . ') ';

function __custom_join_tables($joins) {
  global $wpdb;
  $joins = "JOIN $wpdb->postmeta ON ($wpdb->postmeta.post_ID = $wpdb->posts.ID)";
  return $joins;

Which I was hoping would search only the post title, excerpt and also a single custom field.

It works if I remove the join but really need to keep that included, can anyone see where I have gone wrong?

share|improve this question
Where is __adapted_search_function hooked? – s_ha_dum Sep 3 '13 at 14:42
I have a add_filter('pre_get_posts','my_filter_the_search',10,1); which then calls the add_filter('posts_search', '__adapted_search_function', 10, 2); – Brob Sep 3 '13 at 14:47

I managed to resolve by extending the query

function extend_search( $search, &$wp_query ) {
    global $wpdb;

    if ( empty( $search ))
        return $search;

    $terms = $wp_query->query_vars[ 's' ];
    $exploded = explode( ' ', $terms );
    if( $exploded === FALSE || count( $exploded ) == 0 )
        $exploded = array( 0 => $terms );

    $search = '';
    foreach( $exploded as $tag ) {
        $search .= " AND (
            ($wpdb->posts.post_title LIKE '%$tag%')
            OR ($wpdb->posts.post_excerpt LIKE '%$tag%')
            OR EXISTS
                SELECT * FROM $wpdb->postmeta
                WHERE post_ID = pl_posts.ID
                    AND meta_key = '--KEY--'
                    AND meta_value LIKE '%$tag%'


    return $search;
share|improve this answer

pre_get_posts only takes one parameter but you seems to be using it as if it were posts_where. That isn't really have pre_get_posts works. You have to modify the $query object passed into it, not construct and return a SQL clause.

It isn't possible for me to easily test this but I think the hook you want is either posts_where or the posts_search filter which logically makes the most sense.

add_action('posts_where', '__adapted_search_function',1,2);


add_action('posts_search', '__adapted_search_function',1,2);

You may need to modify the code but changing the hook you are using is key.

share|improve this answer
This is what I have pastebin.com/7PQDyFhY – Brob Sep 3 '13 at 15:23

Your Answer


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.