2

I'm developing a WP plugin which uses custom post types and meta data. What I'm trying to achieve is having the meta data searchable. Here is some code that I found which searches the meta data fine, however I can't get it to display the search string on the CPT page.

CPT Search Error

add_filter( "pre_get_posts", "custom_search_query");
function custom_search_query( $query ) {
    $custom_fields = array(
        "pctracker_company",
        "pctracker_customer",
        "pctracker_phone1",
        "pctracker_phone2",
        "pctracker_mobile",
        "pctracker_email"

    );
    $searchterm = $query->query_vars['s'];
    $query->query_vars['s'] = "";
    if ($searchterm != "") {
        $meta_query = array('relation' => 'OR');
        foreach($custom_fields as $cf){
            array_push($meta_query, array(
                'key' => $cf,
                'value' => $searchterm,
                'compare' => 'LIKE'
            ));
        }
        $query->set("meta_query", $meta_query);
    };
}

I know that in the code its unsetting 'S', however if you don't unset it, it does not display any results.

Can anyone point me in the right direction?

Thanks very much, Jason

EDIT:

I've just been having a play around and I've got this working!

function my_search_results($query){
    if(isset($_GET['s'])){
        if($_GET['post_type'] == "pctracker_customers") {
            $mySearch = $_REQUEST['s'];
            $query = 'select * from wp_posts,wp_postmeta WHERE wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = "pctracker_phone1" AND wp_postmeta.meta_value LIKE "%'.$mySearch.'%" AND(wp_posts.post_status = "publish")';
        }
    }
    return $query;
}
add_filter( 'posts_request', 'my_search_results');

EDIT 2: I've got multiple meta fields I need to search, pctracker_phone1 and pctracker_phone2 are just a couple. I've edited the SQL code so it searches for both. However the SQL code is going to be massive once all of the other metafields are added. Do you know how I could simplifier this:

$query = 'SELECT * FROM '. $wpdb->prefix .'posts,'. $wpdb->prefix .'postmeta WHERE '. $wpdb->prefix .'posts.ID = '. $wpdb->prefix .'postmeta.post_id AND '. $wpdb->prefix .'postmeta.meta_key = "pctracker_phone1" AND '. $wpdb->prefix .'postmeta.meta_value LIKE "%'.$mySearch.'%" OR '. $wpdb->prefix .'posts.ID = '. $wpdb->prefix .'postmeta.post_id AND '. $wpdb->prefix .'postmeta.meta_key = "pctracker_phone2" AND '. $wpdb->prefix .'postmeta.meta_value LIKE "%'.$mySearch.'%" AND('. $wpdb->prefix .'posts.post_status = "publish") ORDER BY '. $wpdb->prefix .'posts.post_date DESC'; 
6
  • Is the question for front-end or admin search? Also: Is the search running on the default search input field or is there something custom like a drop down that gets populated to process a precise and more fine grained search?
    – kaiser
    Mar 8, 2014 at 15:56
  • Its in the admin side using the default search input.
    – jmutton
    Mar 8, 2014 at 19:43
  • 1
    I've just done an update!
    – jmutton
    Mar 8, 2014 at 21:31
  • Do a esc_attr() or filter_var() on $_REQUEST['s'] to avoid getting hacked. Also post it as an answer instead of an update :)
    – kaiser
    Mar 8, 2014 at 22:53
  • Just added that thanks, just one last question you might be able to help me with...
    – jmutton
    Mar 9, 2014 at 0:42

2 Answers 2

0

The code you found modifies the main query on pre_get_posts and unsets the search terms so WP_Query doesn't run a real search query. What you want is

// Filter the search SQL that is used in the WHERE clause of WP_Query.
apply_filters_ref_array( 'posts_search', array( $search, &$this ) );

which runs previously in WP_Query::get_posts(). This later on adds to the WHERE clause:

$where .= $search . $whichauthor . $whichmimetype;

where the author part is:

" AND ($wpdb->posts.post_author = " . absint($q['author']) . ')';

and the MIME-Type part uses wp_post_mime_type_where() and is

$whichmimetype = wp_post_mime_type_where( $q['post_mime_type'], $wpdb->posts );

If the s query var is set, you can use orderby as well and modify it from a filter:

$search_orderby = apply_filters( 'posts_search_orderby', $search_orderby, $this );

The result of this will be the first ORDER BY SQL argument followed by whatever was specified as default ORDER BY argument. If there was no default, it will fall back to the search argument.

$orderby = $orderby ? $search_orderby . ', ' . $orderby : $search_orderby;

Of course you still can then use the posts_clauses and the related filters. You do an early hands on inspection of your results to check if you managed to get a working query by hooking in on

do_action( 'posts_selection', $where . $groupby . $orderby . $limits . $join );

This will give you the complete final SQL string.

Keep in mind that other plugins might as well jump in on the pre_get_posts, posts_request or posts_clauses, posts_* filters and that you won't really be able to work around such conflicts in a generic way.

2
  • Thanks very much for the reply. Sounds like its very much over my head! :-(
    – jmutton
    Mar 8, 2014 at 14:54
  • @Jason You're welcome :) Anyway, as you can read in the title, this sites audience is developers (and people trying to learn developing). Start with reading about filters, hooks and actions (callbacks) and try the different mentioned filters above. Update your question with what you've tried, where you failed, etc. The first step to evolve is to push yourself hard enough and try things that are over your head :)
    – kaiser
    Mar 8, 2014 at 15:51
-1

I've got multiple meta fields I need to search, pctracker_phone1 and pctracker_phone2 are just a couple. I've edited the SQL code so it searches for both. However the SQL code is going to be massive once all of the other metafields are added. Do you know how I could simplifier this:

function my_search_results($query){
if(isset($_GET['s'])){
    if($_GET['post_type'] == "pctracker_customers") {
        $mySearch = $_REQUEST['s'];
        $query = 'SELECT * FROM '. $wpdb->prefix .'posts,'. $wpdb->prefix .'postmeta WHERE '. $wpdb->prefix .'posts.ID = '. $wpdb->prefix .'postmeta.post_id AND '. $wpdb->prefix .'postmeta.meta_key = "pctracker_phone1" AND '. $wpdb->prefix .'postmeta.meta_value LIKE "%'.$mySearch.'%" OR '. $wpdb->prefix .'posts.ID = '. $wpdb->prefix .'postmeta.post_id AND '. $wpdb->prefix .'postmeta.meta_key = "pctracker_phone2" AND '. $wpdb->prefix .'postmeta.meta_value LIKE "%'.$mySearch.'%" AND('. $wpdb->prefix .'posts.post_status = "publish") ORDER BY '. $wpdb->prefix .'posts.post_date DESC'; 
    }
}
return $query;
}
add_filter( 'posts_request', 'my_search_results');
1
  • Please update/edit your question with that info. Don´t add new answers to ask additional questions.
    – kaiser
    Mar 19, 2014 at 20:46

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.