Designs By Nick the Geek

Genesis Based WordPress Development and Tutorials for Everyone

  • Email
  • GitHub
  • Twitter
  • Home
  • About
    • My Experience As…
    • Bedtime Stories by Me
  • Themes
  • Genesis Explained
    • Actions
    • Filters
    • Functions
    • Admin
  • Plugins
  • Themes
    • Free
      • Fluid
  • Tutorials
    • Quick Tips
nickthegeek January 6, 2012

Custom Post Types Made Easy

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?

If you liked this article, tell someone about it

Previous Article

genesis related postsShow Related Posts with Thumbnails in Genesis

Next Article

Social Menu Icons Using Sprites

Related Posts

  • Madlib style contact form and example text
  • WordPress 3.4 and Genesis
  • some plugins don't work or should be usedMust Have Plugins are a Myth
  • Conditional Loop Actions
  • Creating Page Templates in Genesis

Filed Under: Tutorials Tagged: Post Types, Quick Tips, WordPress

Comments

  1. Travis Smith says

    January 10, 2012 at 9:36 pm

    Hello Nick,

    I love this approach. Previously I was using a function to create labels, which I merged with your function.

    // A helper function for generating the labels
    function wps_post_type_labels( $singular, $plural = '' ) {
        if ( $plural == '') $plural = $singular .'s';
      
        return array(
            'name' => _x( $plural, 'post type general name' ),
            'singular_name' => _x( $singular, 'post type singular name' ),
            'add_new' => __( 'Add New' , CHILD_DOMAIN ),
            'add_new_item' => __( 'Add New '. $singular , CHILD_DOMAIN ),
            'edit_item' => __( 'Edit '. $singular , CHILD_DOMAIN ),
            'new_item' => __( 'New '. $singular , CHILD_DOMAIN ),
            'view_item' => __( 'View '. $singular , CHILD_DOMAIN ),
            'search_items' => __( 'Search '. $plural , CHILD_DOMAIN ),
            'not_found' =>  __( 'No '. $plural .' found' , CHILD_DOMAIN ),
            'not_found_in_trash' => __( 'No '. $plural .' found in Trash' , CHILD_DOMAIN ),
            'parent_item_colon' => ''
        );
    }
    • nickthegeek says

      January 10, 2012 at 10:15 pm

      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.

  2. Cindi says

    January 11, 2012 at 7:24 pm

    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

      January 11, 2012 at 9:12 pm

      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.

  3. Alan Smith says

    March 28, 2012 at 9:08 am

    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

      March 28, 2012 at 9:29 am

      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

      add_action( 'init', 'child_init' );
      /**Loads the init.php file*/
      function child_init() {
      
          require( CHILD_DIR . 'lib/init.php' );
      
      }
      

      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

        October 27, 2012 at 4:47 am

        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

          November 1, 2012 at 4:22 pm

          make sure you require the php file with either require() or include()

  4. Pipeline says

    April 2, 2012 at 5:29 pm

    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

      April 3, 2012 at 8:38 am

      You need to check out my conditional code article.
      http://nickc.co/conditional-content

  5. Mark R. says

    December 5, 2012 at 2:47 am

    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.

  6. Mark R. says

    December 5, 2012 at 3:03 am

    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?

Copyright © 2025 Nick the Geek ·Built on the Genesis Theme Framework using the Streamline 2.0 theme · Log in

 

Loading Comments...