I have a custom post type and would like to search titles AND a custom meta key. I have tried several different things, but can only search through titles OR my custom meta key, not both. I don't need to search through content.
Here is what I have that successfully searches my meta key, but it does not search the title.
add_action( 'pre_get_posts', 'filter_files_admin_columns' );
function filter_files_admin_columns( $query ) {
if ( !is_admin() || 'eri-files' !== $query->get( 'post_type' ) ) {
return;
}
// Clear the default 's' search parameter
$search_term = $query->get( 's' );
$query->set( 's', '' );
if ( !empty( $search_term ) ) {
$meta_query = [
'relation' => 'OR',
[
'key' => '',
'value' => $search_term,
'compare' => 'LIKE',
],
];
// Define custom fields to search through
$custom_fields = [ '_post_url' ];
// Build meta query
foreach ( $custom_fields as $custom_field ) {
$meta_query[] = [
'key' => $custom_field,
'value' => $search_term,
'compare' => 'LIKE',
];
}
// Set the meta_query
$query->set( 'meta_query', $meta_query );
}
}
I tried just starting with $meta_query = [ 'relation' => 'OR' ];
, as well as changing the first key to 'post_title'
, but no dice.
I understand that clearing the search term with $query->set( 's', '' );
is preventing searching for the title, but without it I cannot get it to search through the meta key. So I am trying to add support for title back in. If there is a different way to get it to search my meta key without clearing the search term, then please let me know.
I have a custom post type and would like to search titles AND a custom meta key. I have tried several different things, but can only search through titles OR my custom meta key, not both. I don't need to search through content.
Here is what I have that successfully searches my meta key, but it does not search the title.
add_action( 'pre_get_posts', 'filter_files_admin_columns' );
function filter_files_admin_columns( $query ) {
if ( !is_admin() || 'eri-files' !== $query->get( 'post_type' ) ) {
return;
}
// Clear the default 's' search parameter
$search_term = $query->get( 's' );
$query->set( 's', '' );
if ( !empty( $search_term ) ) {
$meta_query = [
'relation' => 'OR',
[
'key' => '',
'value' => $search_term,
'compare' => 'LIKE',
],
];
// Define custom fields to search through
$custom_fields = [ '_post_url' ];
// Build meta query
foreach ( $custom_fields as $custom_field ) {
$meta_query[] = [
'key' => $custom_field,
'value' => $search_term,
'compare' => 'LIKE',
];
}
// Set the meta_query
$query->set( 'meta_query', $meta_query );
}
}
I tried just starting with $meta_query = [ 'relation' => 'OR' ];
, as well as changing the first key to 'post_title'
, but no dice.
I understand that clearing the search term with $query->set( 's', '' );
is preventing searching for the title, but without it I cannot get it to search through the meta key. So I am trying to add support for title back in. If there is a different way to get it to search my meta key without clearing the search term, then please let me know.
After posting the same question to multiple AI chatbots, CoPilot finally gave me an answer that works for both:
add_action( 'pre_get_posts', 'filter_files_admin_columns' );
function filter_files_admin_columns( $query ) {
if ( !is_admin() || 'eri-files' !== $query->get( 'post_type' ) ) {
return;
}
add_filter( 'posts_search', 'custom_search_query', 10, 2 );
function custom_search_query( $search, $wp_query ) {
global $wpdb;
if ( empty( $search ) ) {
return $search;
}
$search_term = $wp_query->get( 's' );
if ( ! $search_term ) {
return $search;
}
$search = "AND (
{$wpdb->posts}.post_title LIKE '%" . esc_sql( $wpdb->esc_like( $search_term ) ) . "%'
OR {$wpdb->posts}.ID IN (
SELECT post_id
FROM {$wpdb->postmeta}
WHERE meta_key = '_post_url'
AND meta_value LIKE '%" . esc_sql( $wpdb->esc_like( $search_term ) ) . "%'
)
)";
return $search;
}
}
The post's title is not stored in meta data, so adding it there won't work. I suspect that keeping the s
parameter and having the meta_query
for _post_url
(custom meta key) should work (untested):
add_action( 'pre_get_posts', static function ( $query ) {
if ( ! is_admin() || 'eri-files' !== $query->get( 'post_type' ) ) {
return;
}
if ( empty( $query->get( 's' ) ) {
return;
}
$query->set( 'meta_query', array(
array(
'key' => '_post_url',
'value' => $query->get( 's' ),
'compare' => 'LIKE',
),
) );
// Limit search to post_title column.
$query->set( 'search_columns', array( 'post_title' ) );
} );
This should return posts where both the post title and _post_url
meta data match the search term.