Development & EngineeringJan 24, 2023
How can I extend the search in WordPress to include custom post types? (Guide, 2023)
By default, custom post types are not included in the WordPress search. But as always with WordPress, there is a hook that allows us to extend/customize the search right away. In no time, you will have adjusted the search.
How to extend the WordPress search with PHP to include custom post types
The hook we need to extend the search is called pre_get_posts. Below, I will show you various snippets that will adjust your search.
Code snippet for PHP 8
If your server already supports PHP 8, we recommend the following snippet to adjust your search:
/**
* This function extends the default WordPress WP_Query object
* to include an array of post types instead of the default 'post'
* post type.
*/
function add_post_types_to_search_query(WP_Query $query): void{
// Skip if this call has been triggered for an administrative interface page.
if(is_admin()){
return;
}
// Skip this call if this is not the search query and if this is not the main query.
if(!$query->is_search() || !$query->is_main_query()){
return;
}
// Define which post types should be searched
$list_of_post_types = ['post', 'pages'];
// Now - if we get to this point, this must be the search query which we will modify.
$query->set('post_type', $list_of_post_types);
}
add_action('pre_get_posts', 'add_post_types_to_search_query', 10, 1);Alternative: Code snippet for PHP 7
You should only use this code if PHP 8 is not yet running on your server or your site is not compatible with PHP 8.
/**
* This function extends the default WordPress WP_Query object
* to include an array of post types instead of the default 'post'
* post type.
*/
function add_post_types_to_search_query($query){
// Skip if this call has been triggered for an administrative interface page.
if(is_admin()){
return;
}
// Skip this call if this is not the search query and if this is not the main query.
if(!$query->is_search() || !$query->is_main_query()){
return;
}
// Define which post types should be searched. Replace/Extend by your post types.
$list_of_post_types = array('post', 'pages');
// Now - if we get to this point, this must be the search query which we will modify.
$query->set('post_type', $list_of_post_types);
}
add_action('pre_get_posts', 'add_post_types_to_search_query', 10, 1);Long-term easy maintenance thanks to OOP, code snippet
Here is an example of how you can implement this with a class and namespaces if you want to keep maintenance effort low in the long term.
namespace My_Search{
/**
* This class extends the default WordPress WP_Query object
* to include an array of post types instead of the default 'post'
* post type.
*/
class Search_Query_Post_Type_Modifier{
/**
* There should never be more than one object of this class therefore
* we need to create a Singleton
*/
private static ?Search_Query_Post_Type_Modifier $_instance = null;
/**
* This function will allow us to access the instance of this class
*/
public static function get_instance(): Search_Query_Post_Type_Modifier{
if(null === self::$_instance){
self::$_instance = new Search_Query_Post_Type_Modifier();
}
return self::$_instance;
}
/**
* Private constructor to disable multiple instances of this object.
*/
private function __construct(){
add_action('pre_get_posts', [$this, 'add_post_types_to_query']);
}
/**
* Add the post types to the search query
*/
public function add_post_types_to_query(WP_Query $query): void{
// Skip if this call has been triggered for an administrative interface page.
if(is_admin()){
return;
}
// Skip this call if this is not the search query and if this is not the main query.
if(!$query->is_search() || !$query->is_main_query()){
return;
}
// Define which post types should be searched
$list_of_post_types = ['post', 'pages'];
// Now - if we get to this point, this must be the search query which we will modify.
$query->set('post_type', $list_of_post_types);
}
}
/**
* Instantiate the object
*/
Search_Query_Post_Type_Modifier::get_instance();
}As few lines of code as possible:
This version is designed to use as few lines of code as possible :)
add_action('pre_get_posts', function(WP_Query $query){
if(!is_admin() && $query->is_search() && $query->is_main_query()){
$query->set('post_type', ['post','page']);
}
}, 10, 1);