» » » Search by Custom Fields without a plugin

Search by Custom Fields without a plugin

posted in: WordPress
1 min read

Lately, my client requires me to add the ability to search by custom fields at the backend. Today I gonna share what I did.

There are three filters we will use.

Below what page will be implemented.

You can add the code below into functions.php or your own plugin. $_GET[‘s’] is the search input on the edit page. The posts_distinct filter is needed to prevent duplicate data.

add_filter('posts_join', 'package_customfields_search_join');
function package_customfields_search_join($join)
{
    global $pagenow, $wpdb;
    if (is_admin() && 'edit.php' === $pagenow && 'packages' === $_GET['post_type'] && !empty($_GET['s'])) {
        $join .= 'LEFT JOIN ' . $wpdb->postmeta . ' ON ' . $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    return $join;
}

add_filter('posts_where', 'package_customfields_search_where');
function package_customfields_search_where($where)
{
    global $pagenow, $wpdb;
    if (is_admin() && 'edit.php' === $pagenow && 'packages' === $_GET['post_type'] && !empty($_GET['s'])) {
        $where = preg_replace(
            "/\(\s*" . $wpdb->posts . ".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            "(" . $wpdb->posts . ".post_title LIKE $1) OR (" . $wpdb->postmeta . ".meta_value LIKE $1)",
            $where
        );
    }
    return $where;
}

add_filter('posts_distinct', 'package_search_distinct');
function package_search_distinct($where)
{
    global $pagenow, $wpdb;
    if (is_admin() && 'edit.php' === $pagenow && 'packages' === $_GET['post_type'] && !empty($_GET['s']) && is_search()) {
        return "DISTINCT";
    }

    return $where;
}

Yeap! that’s it. If you are looking for adding the custom fields filter, you may check my post here.