6

I have a custom post type that includes many custom fields. I would like to add them as a search target to admin search.

Currently the admin search searches only the content and the title, I would like it to search these custom fields as well.

Is there a way to do that ?

5

It is possible, but you'll have to play a little bit with the actual query. As always, the furious posts_clauses filter comes to action:

function wpse_alter_posts_search( $pieces )
{
    global $wpdb;

    // Make the input save
    $search_string = like_escape( $_GET['s'] );

    // Your new WHERE clause
    $where  = $wpdb->prepare(
        "$wpdb->postmeta.%s LIKE %s",
        'YOUR_COLUMN', // Should match your col name 1)
        "%{$search_string}%"
    );

    // Not sure if this exactly the same on your install 2)
    $pieces['where'] = str_replace( 'AND (((', "AND ((({$where} ", $pieces['where'] );

    return $pieces;
}
add_filter( 'posts_clauses', 'wpse_alter_posts_search' );

NOTES

  1. Could be that you need to unserialize some parts to be search able.
  2. You better simply dump the $pieces to take a look into them, before altering the query (right after the $search_string was received).
  • Or posts_where :D – Stephen Harris Mar 8 '12 at 18:15
  • @StephenHarris I personally prefer the »alltogether« posts_clauses filter. No need to remember those (imho unnecessary) other filters... – kaiser Mar 8 '12 at 18:16
  • I guess like_escape should be a function that escapes the search string to like format. can you please add it ? I'me having problems with this... – hannit cohen Mar 9 '12 at 13:20
  • Added like_escape()ed to the prepare(). And no: It doesn't reformat the input search string. It makes it just save for queries, like other esc_* functions do for other tasks. – kaiser Mar 9 '12 at 13:32
1

kaiser's answer got me on the right track but I had to join the postmeta table and add a group by as well.

Now like_escape is $wpdb->esc_like. Replace [your_post_type] with your post type and [your_postmeta_key] with your meta key:

//join postmeta for search
add_filter( 'posts_join' , function($join){
    global $wpdb;
    if(is_search() && is_admin() && $_GET['post_type'] == '[your_post_type]')
    {
     $join .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";
    }
     return $join;
});

//search [your_postmeta_key] for search string
add_filter( 'posts_where', function( $where )
{
    global $wpdb;
    if(is_search() && is_admin() && $_GET['post_type'] == '[your_post_type]')
    {
        $searchstring = '%' . $wpdb->esc_like( $_GET['s'] ) . '%';
        //search [your_postmeta_key] as well
        $where .= $wpdb->prepare(" OR ($wpdb->postmeta.meta_key = '[your_postmeta_key]' AND $wpdb->postmeta.meta_value LIKE %s) ", $searchstring);   
    }
    return $where;
});

//group by post ID
add_filter( 'posts_groupby', function ($groupby, $query) {

    global $wpdb;
    if(is_search() && is_admin() && $_GET['post_type'] == '[your_post_type]')
    {
        $groupby = "{$wpdb->posts}.ID";
    }
    return $groupby;

}, 10, 2 );

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.