php - How to allow searching a custom meta key in admin list table?

admin2025-01-07  5

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.

Share Improve this question asked Dec 20, 2024 at 18:16 AristoclesAristocles 1397 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

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.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1736258114a490.html

最新回复(0)