Post types aren’t really that hard to start with. You start with some template code, then make a few changes and bam! Now you have a custom post type. However, teh code can get clunky if you register several CPTs. On this blog I have a single CPT, for the child themes used by my Child Theme Matrix. I use some template code I picked up when I first read about custom post types. You can find that article and a lot of information on CPTs on Justin’s article on Custom Post Types.
However, sometimes your client wants a CPT for videos, image galleries, and …. When faced with a growing list of post types and no reasonable objection (sometimes post types really are the right answer but most of the time I do try to convince my clients to work within posts and pages, after all, we did that exclusively until a little while ago), registering each CPT can become an annoying task.
Recently I had a job where we started with just 1 CPT, then 2, 3, 4, …. It wasn’t all at once but I eventually looked at the code and realized I can get rid of a lot of repeated lines. It makes the code prettier if not more efficient. I had looked at other code for registering CPTs and realized I can make it even more simple.
This is what I’m using now
/** * Registers a post type with default values which can be overridden as needed. * * @author Nick the Geek * @link https://designsbynickthegeek.com/tutorials/custom-post-types-made-easy * * @uses sanitize_title() WordPress function that formats text for use as a slug * @uses wp_parse_args() WordPress function that merges two arrays and parses the values to override defaults * @uses register_post_type() WordPress function for registering a new post type * * @param string $title title of the post type. This will be automatically converted for plural and slug use * @param array $args overrides the defaults */ function ntg_register_post_type( $title, $args = array() ){ $sanitizedTitle = sanitize_title( $title ); $defaults = array( 'labels' => array( 'name' => $title . 's', 'singular_name' => $title, 'add_new_item' => 'Add New ' . $title, 'edit_item' => 'Edit ' . $title, 'new_item' => 'New ' . $title, 'search_items' => 'Search ' . $title . 's', 'not_found' => 'No ' . $title . 's found', 'not_found_in_trash' => 'No ' . $title . 's found in trash' ), '_builtin' => false, 'public' => true, 'hierarchical' => false, 'taxonomies' => array( ), 'query_var' => true, 'menu_position' => 6, 'supports' => array( 'title', 'editor', 'thumbnail', 'author', 'comments', 'genesis-seo' ), 'rewrite' => array( 'slug' => $sanitizedTitle ), 'has_archive' => true ); $args = wp_parse_args( $args, $defaults ); $postType = isset( $args['postType'] ) ? $args['postType'] : $sanitizedTitle; register_post_type( $postType, $args ); }
Basically, there is only one required parameter, the Title. However, you can change any other value by using the array. So you can do this
// Register post type "foo" ntg_register_post_type( 'Foo' ); // Register post type "bar" without an archive ntg_register_post_type( 'Bar', array( 'has_archive' => false ) ); // Register post type "geeks" with the title Nick's Peeps ntg_register_post_type( 'Nick\'s Peeps', array( 'postType' => 'geeks', rewrite => array( 'slug' => 'geek' ) ) );
I’m sure you can see how this can save a lot of time, you might even build an array like this.
$postTypes = array( 'Foo' => '', 'Bar' => array( 'has_archive' => false ), 'Nick\'s Peeps' => array( 'postType' => 'geeks', rewrite => array( 'slug' => 'geek' ) ) ); foreach( $postTypes as $title => $args ) ntg_register_post_type( $title, $args );
How are you using post types? Do you use functions or classes to handle your post type registration?
Travis Smith says
Hello Nick,
I love this approach. Previously I was using a function to create labels, which I merged with your function.
nickthegeek says
I had not thought of building an object like that, I’ve been kicking around the idea of doing a full on class to handle post types and taxonomies. That would make for a good method with a couple small adjustments.
Cindi says
Do custom post types add to the CPU load above and beyond normal posts? I’ve been throttled by Bluehost just as I was preparing to roll out custom post types. I’m being very cautious now.
nickthegeek says
It is going to add additional CPU load since there is additional code, but the code is pretty minimal and the overhead isn’t really significantly different than posts and pages, which are internal post types. However, if you are thinking about using CPTs, take a step back and evaluate why you want them. In some cases you need a CPT, but often you would be better served by proper use of categories.
Alan Smith says
Am I understanding this properly? You use the “Register Post Type with defaults” section as the code for all CPT you would need/want for a site. Then when you need to create a new CPT, just add the register_post_type(title)?
Do you recommend putting the main code in the functions.php or placing it in a separate file and making add_action call for it in functions.php?
Good post!
nickthegeek says
Alan, well I only use this if I’m going to be registering several post types. Most of the time I just need a single post type for a client and don’t worry about this.
When I do use it, I will typically put this function in the functions.php file, then require a post_types_taxonomies.php file that I register the post types and taxonomies. I put the require() function on an init action, since the post_types and taxonomies should be registered on init. So it looks like
Then in the init file I can run functions that are supposed to be on init, and I can require the /lib/ files like /lib/post_types_taxonomies.php
thebluegger says
Nick – Thanks for all the great tutes. Learning a lot. 🙂
Had a doubt.
Created a .php file, with some code for registering a CPT, and put it into a child theme folder.
Typed the above “add_action” step in child theme’s functions.php file. However, the CPT did not get registered.
Am I doing something wrong?
No hurry. Take your time, for a reply. 🙂 I’m only playing around. Nothing urgent.
Cheers.
nickthegeek says
make sure you require the php file with either require() or include()
Pipeline says
Hi, im using genesis 1.8 with agentpress and im trying to call via the genesis_post_content hook the shortcode [property_details] inside every listing created by user using gravity forms. But if i use just the shortcode it is called on every single post. What code should i insert into the hook (im using genesis simple hooks plugin) to test if post type is “listing” and display the property_details, and prevent it to showing up in blog posts and pages? Tried different ways but didnt make it… Thanks in advance for the help.
nickthegeek says
You need to check out my conditional code article.
http://nickc.co/conditional-content
Mark R. says
Nick, quick question about Genesis Media Project and the custom video post type there. How can I create a custom menu item to display only the videos belonging to a certain Video Category? Why have categories if they cannot be used to filter a video library? Good for only organizing the library in admin? Whether Video Category or Video Tag, I would like to use one or the other or both as a search criteria and attach the URL string to a menu item…..think Categories menu, and a list of options underneath, each a URL to a different Video Category.
Thanks for an answer, and sorry if you have answered this elsewhere.
Mark R. says
Nick, ignore that last post! Figured out the URL format for video categories. Yes, the link format is obvious: http://myURL/video-category/actual-category-slug/
And creating the menu is also obvious.
But….can you offer any advice on how best to display the results? With the URL above, I get the videos in a basic linear blog post page format (not sure which template file yet..). Advice? Ultimately, I think a grid format would be best for such a filter process. The category choice produces a grid of videos or at least thumbnails in Portfolio Page style common to some of the Genesis themes.
Ideas to share? How do we set the template for the results of such a category results page for video categories?