You can use the pre_get_posts
hook. Do note though, this hook filters the query on both the front-end and admin. For example, we could do something like this:
function search_post_types( $query ) {
if( is_admin() ) {
return $query;
}
if ( $query->is_search && $query->is_main_query() ) {
$query->set( 'post_type', array( 'post', 'page' ) );
}
}
add_action( 'pre_get_posts', 'search_post_types' );
I’m not sure there’s a way to exclude it using pre_get_posts
but more along the lines of include specific post types only, in the example above I’m only including Posts and Pages, nothing else.
Another method is to get all post types and create an array of post types we actually want to exclude. First we use the function get_post_types()
which does have some arguments to exclude built-in post types but for this example we will get everything. Once we’ve gotten our post types we can create an exclude array and array_diff()
, here’s what it looks like:
function search_post_types( $query ) {
if( is_admin() ) {
return $query;
}
if ( $query->is_search && $query->is_main_query() ) {
$post_types = get_post_types( array(), 'names' ); // With no arguments, this should never be empty
if( ! empty( $post_types ) ) { // But let's check just to be safe!
$pt_exclude = array( 'attachment', 'revision', 'nav_menu_item' );
$pt_include = array_diff( $post_types, $pt_exclude );
$query->set( 'post_type', $pt_include );
}
}
}
add_action( 'pre_get_posts', 'search_post_types' );