I have a couple of custom post types registered. I would like to display all “posts” from each custom post type on its own page, and these pages must be visible in the nav menu.
It would be great to only have one page-custom.php
template as to a page template for each custom post type. Is it possible to create something like this?
REVISIT: Feb. 2nd 2016
The original code had many issues
Data wasn’t sanitized and validated which can lead to serious security issues
Some parts were repetitive
Bit messy and sometimes hard to read
Some sections was only partly working
Used globals which is really evil
That is why I revisited this answer and updated the code in order to solve the issues above. The code is now cleaner, safer and easier to read and debug. Make sure to check it out in the ORIGINAL ANSWER section
Before I go to the original ORIGINAL ANSWER section, I want to add an alternative which I think is a bit better to use
ALTERNATIVE WAY
This is a straight forward alternative solution which does not involve custom templates (except maybe a
content.php
) or modifying any templates. All you need to do iscreate a new page with any page template you wish
create a
content.php
template part of any such template part if your theme does not have these available by defaultadd the following code and your done
The
PreGetPostsForPages
class can be found in my answer here and also a detailed explanation on how to use itORIGINAL ANSWER
If you have a look at the template hierarchy, custom post types are usually displayed on archive templates. Normal template hierarchy does not make provision for
page.php
type templates to be used to display custom post types by default.The problem with archive templates is that they don’t automatically get added to the default nav menu, and creating a custom menu to create links is not always the most convenient way to go.
The way to go here is to use
WP_Query
to create a custom query for the loop to include custom post types.WP_Query
have apost_type
type parameter which is used to call post types.So, the following needs to be modified to make this work:
Firstly, create a custom
page.php
templateTo create the custom
page.php
you need to copy your theme’spage.php
and rename it something likepage-cpt.php
. Now open it and change the loop. For the sake of this answer, I’ve used the default twentyfourteen theme. Delete everything inside the template and replace it with this codeEDIT I have came back to change the code. The previous code used the following in the custom query
which also translate to
query_posts
, which should never be used. So I changes the code accordingly to execute a proper instance ofWP_Query
. Here is the edited codeThe first piece of code is used to call the settings from the db. This will be set via a metabox in the back end when creating a new page in the page editor screen. The important code here is the arguments for
WP_Query
.This will decide which custom post types will be displayed, posts per page and the order of posts. All these settings are called from the db, and is set in the custom meta box in the back end
Secondly, create a custom meta box
This metabox will be diplayed in the “Page” screen when a new page is created and “Custom Post Type Page” is selected in the “Page Attributes” meta box.
Add the following in your
functions.php
or custom functions fileWhat this code do is to register and display the meta box, add the options to the metabox and storing the options to the db for use in the
page-cpt.php
template.You can now go and create a new page, and call the page whatever you like. In the “Page Attributes”, select “Custom Post Type Page” and “Publish” your page. The metabox for the custom post types options will now appear above the “Publish” metabox, and will display all the current available custom post types. Select and set the options you need to display and click “Update”. Your page will now show posts from the custom post type you have selected, and your page will be visible in the nav bar.
You can add more functionality to this, or change the code to display categories or taxonomies in the same way. Hope this help