Bulding off of this response from @kaiser about being able to filter by post types on a search page, I wanted to be able to automatically add-in all of the public post types available. So, after some help with @kaiser, I came up with:
function sw_custom_post_type_includes($query) {
$args = array(
'public' => true
);
$output = 'names'; // names or objects, note names is the default
$operator = 'and'; // 'and' or 'or'
$post_types = get_post_types( $args, $output, $operator );
if ( !is_search() && !in_array( get_post_type(), $post_types ) )
return;
$query->set( 'post_type', $post_types );
return $query;
}
add_filter('pre_get_posts', 'sw_custom_post_type_includes');
Which initially seemed to work great, but I ran into an issue -> everything filtered by post type correctly EXCEPT when I tried to use &post_type=page
. I was actually getting an undefined index error for post_type
. I couldn’t figure out why this wasn’t working. So, I decided to use print_r($query->query_vars)
to see if everything was being pulled in correctly. Low and behold – for all post types EXCEPT for pages, that variable was set.
I conferred with another dev on this and they verified the issue. This is what I ended up using as a workaround:
function sw_custom_post_type_includes($query) {
if(isset($_GET['post_type']) && ((!isset($query->query_vars['post_type'])) || (isset($query->query_vars['post_type']) && $query->query_vars['post_type'] != 'nav_menu_item'))) {
$query->set('post_type', urldecode($_GET['post_type']));
}
}
add_action('pre_get_posts', 'sw_custom_post_type_includes');
This honestly seems like an odd workaround for something that has been baffling me for a few hours. Anyone with input on this will be rewarded with virtual high-fives.
To clear up some confusion in previous answers, pre_get_posts isn’t a filter so you don’t need to return anything.
Your only problem that I see is the if:
Basically get_post_type() is going to return false during pre_get_posts because the global $post hasn’t been set yet (usually set once you start the loop).
I’m not totally sure WHEN you want all public post types and when you don’t. If you just want to set all searches to include all public post types, you really just need to check is_search(). You may also want to make sure the query being modified is the main query and not a custom query that a plugin or theme file is creating. The code should look like this:
That’s it. That will cause all public post types to be queried for searches.
If you want all public post types on the home page and search, use this:
UPDATE:
The problem you are having is unique to post_types that have publicly_queryable set to false. You basically want all public types to work even if they are not publicly_queryable. To do that use this code:
Basically, if a post_type is in URL but NOT in QP_Query, it COULD be because it’s not publicly_queryable, and if so we fix it. Here is what is checked:
If all those are true, it sets the post_type to the one in the URL.
As I answered the question, where this one is a follow up and after commenting a lot on the questions here, I’m pretty sure, that you somewhere got another filter or conditional that is holding you back from retrieving a result for pages. 99% chance that this is your problem. You better start with a blank vanilla installation and try to run nothing than this filter to prove, that it’s working. Then walk in and start removing/commenting out all that custom stuff, deactivate plugins, etc. until you know what’s going on.
you wrote
if
page
is not in your$post_types
array there’s an emptyreturn;
Actually I don’t see why you add this security, this function is called only when there’s an actual need thanks to the
pre_get_posts
filterYou should just change the return:
It’s just a thought, I didn’t try