The only problem is that the default search columns in the wp_posts
table such as post_title seem to no longer be searched.
They’re actually being searched, but the operator used is AND
instead of OR
as in WHERE ( <search query> AND <meta query> )
, hence if for example one searched for foo
, then WordPress will search for posts which..
-
Contain
foo
in the post title/content/excerpt and -
Contain
foo
in the metacity
orstate_county
So if you want the operator be changed to OR
, i.e. search in the post title/content/excerpt or your custom fields, then you can try the following which simply repositions the default search query in the WHERE
clause:
-
This snippet modifies the meta queries (to add your custom fields) and also sets a private arg used as a flag which if true, then we’ll reposition the search query.
add_action( 'pre_get_posts', 'query_custom_admin_search', 21 ); function query_custom_admin_search( $query ) { // Check if the current user has the 'administrator' role. if ( ! in_array( 'administrator', (array) wp_get_current_user()->roles ) ) { return; } // Check if we're on the "Posts" page at wp-admin/edit.php?post_type=apartments // and that a search keyword is set. if ( ! is_admin() || ! $query->is_main_query() || 'edit-apartments' !== get_current_screen()->id || ! strlen( $query->get( 's' ) ) ) { return; } // Retrieve existing meta queries, if any. $meta_query = (array) $query->get( 'meta_query' ); // Define your custom fields (meta keys). $custom_fields = array( 'city', 'state_county' ); // This is for your custom fields above. $meta_query2 = array( 'relation' => 'OR' ); $s = $query->get( 's' ); foreach ( $custom_fields as $meta_key ) { $meta_query2[] = array( 'key' => $meta_key, 'value' => $s, 'compare' => 'LIKE', ); } // Add your meta query to the existing ones in $meta_query. $meta_query[] = $meta_query2; $query->set( 'meta_query', $meta_query ); // Set a custom flag for the posts_search and posts_where. $query->set( '_search_OR', true ); }
-
This snippet uses the
posts_search
hook to “empty” the search query, after storing it in a private arg which we’ll use in theposts_where
hook where we reposition the search query.add_filter( 'posts_search', 'wpse_401476_admin_posts_search', 21, 2 ); function wpse_401476_admin_posts_search( $search, $query ) { if ( $query->get( '_search_OR' ) ) { $query->set( '_search_SQL', $search ); $search=""; } return $search; }
-
Now this snippet is the one that repositions the search query. It uses
WP_Meta_Query::get_sql()
to retrieve the meta query’s (SQL) clauses (join
andwhere
) used in the current query.add_filter( 'posts_where', 'wpse_401476_admin_posts_where', 21, 2 ); function wpse_401476_admin_posts_where( $where, $query ) { if ( $query->get( '_search_OR' ) && $search = $query->get( '_search_SQL' ) ) { global $wpdb; $clauses = $query->meta_query->get_sql( 'post', $wpdb->posts, 'ID', $query ); if ( ! empty( $clauses['where'] ) ) { $where2 = "( 1 $search ) OR ( 1 {$clauses['where']} )"; $where = str_replace( $clauses['where'], " AND ( $where2 )", $where ); $query->set( '_search_SQL', false ); $query->set( '_search_OR', false ); } } return $where; }
So with the above, we’d get a condition that looks like
( ( 1 AND <search query> ) OR ( 1 AND <meta query> ) )
which is equivalent to the( <search query> OR <meta query> )
.
Tried & tested working on WordPress v5.8.3.
Notes:
-
Use the above snippets instead of what you have in the question.
-
The operator would only be changed if the current user has the
administrator
role and that the current page is the admin page for managing posts in theapartments
post type, and that the search keyword is set, and I also checked if the current query/WP_Query
is the main query. -
I used
21
as the priority, hence you might want to use a greater number (e.g.100
) to make the filters apply properly (i.e. not overwritten by plugins or the active theme).