I’m trying to create a plugin which adds a new custom post type and it should be shown at the same locations as a normal post (front page, archives etc.).
Is there any functions for me to retrieve the post types which are currently being called in the query so that I can modify and add my CPT to the current query? (example stated in 2nd comment if my question sounds confusing)
I can’t use the code below (i.e. list the post types) because I can’t predict what post types would the user have :
add_filter( 'pre_get_posts', 'my_get_posts' );
function my_get_posts( $query ) {
if ( is_home() && $query->is_main_query() )
$query->set( 'post_type', array( 'post', 'page', 'album', 'movie', 'quote' ) );
return $query;
}
Similarly, I can’t use the code below because that would return all post types, including those which might not be intended to be shown at the front page :
if ( !is_admin() && empty( $query->query_vars['suppress_filters'] ) && $query->is_main_query() ) {
$post_type = get_query_var('post_type');
$post_types = get_post_types( array( 'public' => true ) );
if ($post_type) {
$post_type = $post_type;
} else {
$post_type = $post_types;
}
$query->set('post_type',$post_type);
return $query;
}
}
So, is there any ideas how I can add my CPT to the query without affecting other post types? Thanks for helping!
You are actually not that far away with pre_get_posts
, you just need to first grab the current post types that are in the query before adding your own.
Also, I’d recommend using a $priority
of 99
so that the action is hooked after any other pre_get_posts
hooks, meaning that if users add there own CPT’s (or built in post types) they are detected and included by the function below (but you can change that as required).
add_action('pre_get_posts', 'djg_includ_my_cpt_in_query', 99);
function djg_includ_my_cpt_in_query($query){
if(is_home() && $query->is_main_query()) : // Ensure you only alter your desired query
$post_types = $query->get('post_type'); // Get the currnet post types in the query
if(!is_array($post_types) && !empty($post_types)) // Check that the current posts types are stored as an array
$post_types = explode(',', $post_types);
if(empty($post_types)) // If there are no post types defined, be sure to include posts so that they are not ignored
$post_types[] = 'post';
$post_types[] = 'document'; // Add your custom post type
$post_types = array_map('trim', $post_types); // Trim every element, just in case
$post_types = array_filter($post_types); // Remove any empty elements, just in case
$query->set('post_type', $post_types); // Add the updated list of post types to your query
endif;
return $query;
}
EDIT
When constructing the final query, WordPress checks to see if ‘post_type’ is empty, and if so the following code is executed –
$where .= " AND $wpdb->posts.post_type="post"";
$post_type_object = get_post_type_object ( 'post' );
So what happens when we add a CPT is that WordPress assuems we want to ignore posts as it is not explicitly declared. That is were my scenario differed – I had explicitly declared other post types previously so they were included in the call $post_types = $query->get('post_type');
.
So, in your case we can resonably summise that if $post_types
is empty, the user does not wish to amend that portion of the query so ‘post’ can be manually added to the $post_types
array. This should (hopefully!) do the trick.