Every day more websites use the Post Types extension of WordPress. They are not publishing just (simple) posts but they publish recipes, people profiles, city reviews, testimonials, or whatever you could imagine. It’s fantastic to be able to works easily with all these kinks of different information both in Front End and Back End however, when you access to your Front Page these Post Types aren’t shown in the results list of the main query. Are they shy? What can we do?
This behaviour is because of the relationship between the kind of executed WP query and the URL that you are typing in your browser. When you register a new Post Type inside your themes or plugins, WordPress automatically creates a new set of rules –through the rewrite module– that allow to us to use the new URLs (slug) associated with their Archive or Single templates respectively. You type these urls, and the results always appears instantly. These new rewrite rules connect the structure of each one of the urls associated with a Post Type with specific SQL queries. But this behaviour is not applied to the Main Page. In fact, Main page has always got the same URL so has always got the same Query. See some examples.
you type this URL: http://mysite.com/books
/ and then WP executes SQL> SELECT * FROM wp_posts WHERE post_type = 'book'; // more or less you type this URL: http://mysite.com/book/12341
/ and then WP executes SQL> SELECT * FROM wp_posts WHERE post_type = 'book' AND ID = 12341; But if you type the main URL:http://mysite.com/
, then WP executes its default main query SQL> SELECT * FROM wp_posts WHERE post_type = 'post';
The main WP SQL query is always the same regardless of how many different Post Types have already been declared. At the beginning of working with WordPress, this behaviour is so confusing because we think that in the same way that the new post types have their new URLs –and they work–, the new post types must also appear automaticaly in the main page.
The reasons of this WP development decision are many, and are also actually suitable and, without going into details, this decision is, for example, related with the template used to show a the content of a post type, related to allow the developers for using post types as tools (menus, forms), related to… Ok, perhaps in other article will talk about philosophy, now, better let’s go to the solution.
For the example, if we have declared two more Post Types (Books and Dogs), the core of our solucion is to convert the default WP main SQL query in a new SQL query (more or less) like this.
the default SQL: SQL> SELECT * FROM wp_posts WHERE post_type=
'post'; Our proposed SQL: SQL> SELECT * FROM wp_posts WHERE post_typeIN
( 'post', 'book', 'dog' ); // More or less.
And to do this change, we have to work with a filter that’s called while the SQL query is been constructed and before it is launched against MySQL database for its execution. This filter is called pre_get_posts
, and we will use it to introduce the list of the post types that we want to show in Front Page; for our example, we want to add Books and Dogs in the Front Page Results.
<?php function add_books_and_dogs ( $query ) { // we avoid to change precisely for the post type archive queries if ( ( $query->is_main_query() ) && ( isset( $query->query_vars['post_type'] ) && is_string( $query->query_vars['post_type'] ) ) ) return $query; if ( ( $query->is_main_query() ) && ( is_home() ) ) { $pt_array[] = 'post'; $pt_array[] = 'dog'; $pt_array[] = 'book'; $query->set( 'post_type', $pt_array ); } return $query; } if ( ! is_admin() ) add_filter( 'pre_get_posts', 'add_books_and_dogs', 99, 1 ); ?>
Of course, you are allow to improve this method, for example checking previously the value of post_type query variable, or including these new post types also in the query of searches, etc.
Be careful with the priority of the filter, you need execute it at the end of construction of SQL sentence, so 99 should be enogh.
Have a nice WordPressing!