Add CPT to search results non-destructively?

The following amends the core search query to include a custom post type in the results.

function myprefix_amend_search_query($query) {
    if (!$query->is_search) {
        return $query;
    }

    $post_types_to_include = [
        'post',
        'page',
        'my_cpt'
    ];

    $query->set('post_type', $post_types_to_include);

    return $query;

}
add_filter('pre_get_posts', 'myprefix_amend_search_query');

The above does not account for cases where other plugins may have included their own CPTs in the results. To solve for this, we can use any, as follows:

function myprefix_amend_search_query($query) {
    if (!$query->is_search) {
        return $query;
    }

    $query->set('post_type', 'any');

    return $query;

}
add_filter('pre_get_posts', 'myprefix_amend_search_query');

However, it seems like using any may include items that are unintended for search in some cases.

So, the question is: what is the proper way to amend the query to include a few new custom post types while not interfering with any other plugins that may also be adding custom post types to core search?

2 Likes

Just merge your CPTs into whatever is already there:

$my_types = ['my_cpt'];
$their_types = $query->get('post_type');
// @todo: make sure $their_types is an array
$query->set('post_type', array_merge($their_types, $my_types));

(Not tested but should be pretty close to working).

2 Likes

I tried and tried $query->get('post_type'); and it kept coming back empty, so, I thought something wasn’t working quite right. Off on a tangent I went…lol. I realize now it was a simple priority issue. I was testing with a plugin named aaa, so, being the first plugin loaded, $query->get('post_type'); should come back empty since no other plugins had a chance to register their post types for search. I’m going to set a higher priority on the hook to ensure that it fires after others, just in case another plugin didn’t get it right…like I almost didn’t. :slight_smile: Thanks for getting me back on track. Here’s the final working code if anyone else needs it.

function update_search_query($query) {

    // Not a search? Bail.
    if (!$query->is_search) {
        return $query;
    }

    // Currently searchable post types.
    $post_types_in_search = $query->get('post_type');

    // New post types to add to search.
    $post_types_to_include = [
        'my_cool_cpt',
        'my_neat_cpt',
    ];

    // Update the query.
    $query->set('post_type', array_merge($post_types_in_search, $post_types_to_include));

    // Return the query.
    return $query;

}

add_filter('pre_get_posts', 'amend_search_query', 100); // Note the late priority.
2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.