Custom Post Types with Genesis

This is a tutorial showing how to add a custom post type with custom metaboxes in WordPress. We’ll take it one step further and create a page template to display the new post type using the Genesis Framework. I’ve learned that there’s a “Genesis way” of doing things, so I wanted to share that here.

The example we’ll build here is a coupon post type, where the site owner can fill out a few fields, and WordPress generates a coupon.

Some Background on Custom Post Types and Custom Meta Boxes

If you haven’t read Justin Tadlock’s excellent writeup about Custom Post Types, you really should.
In this example, we’re going to create some custom meta boxes to make it easy for the site owner to enter the coupon information. If you want custom meta boxes for your project, I suggest you work through Devin Price’s step by step tutorial about How to Add a Metabox to a Custom Post Type. That’s what I did. I added three custom fields for the amount, description and expiration of each coupon.
For the typical WordPress theme, you would use the get_post_meta() function to display the custom fields in a custom template. For Genesis, we’re going to do things a bit differently.

Page Templates and Custom Fields the Genesis Way

So here’s the heart of this tutorial. Once you’ve got your custom post types registered and meta boxes working, you’ll want to display this stuff in a template. Here we go:
Create a new file in your child theme. In this example I’m going to name it page_special.php, as the custom post type I’m working with here is named “special”.

Here’s the code and markup for this page template, note the comments:

<?php
/*
Template Name: Special
*/

remove_action('genesis_post_title', 'genesis_do_post_title');//We're not using the title for this post type
remove_action('genesis_loop', 'genesis_do_loop');//remove genesis loop
add_action('genesis_loop', 'special_loop');//add the special loop

function special_loop() {

	$loop = new WP_Query( array( 'post_type' => 'special', 'posts_per_page' => 20 ) ); ?>
				<h1><?php the_title(); ?></h1>
			<div id="specials">
	<?php while ( $loop->have_posts() ) : $loop->the_post(); ?>
		<div id="post-<?php the_ID(); ?>" class="coupon">
			<?php//use the genesis_get_custom_field template tag to display each custom field value ?>
			<h3><?php echo genesis_get_custom_field('_amount'); ?></h3>
			<p class="special"><?php echo genesis_get_custom_field('_description'); ?></p>
			<p class="expiration">Expires on:&nbsp;<?php echo genesis_get_custom_field('_expiration'); ?></p>
			</div><!--end #specials -->
	<?php endwhile;?>
	<?php
	}

	genesis();

You’ll notice that building a custom page template in Genesis is a little different as you need to remove the loop, then add your custom loop. Also, instead of using the get_post_meta() function, we’re using genesis_get_custom_field(), that’s the Genesis way of doing things. So this will loop through and display each special on the page.

You’ll notice the liberal use of class names for each displayed field. They provide hooks for styling the actual coupons. I’m not going to get into the CSS end of things on this tutorial, you’ll have your own design constraints that you’re working with.

Here’s the custom post type in the editor:

Custom post type meta box

Finally, create a new page in WordPress and select the newly created page template.

Here’s the finished coupon:

Custom post type coupon

I might have left out a step, or you might have a better way to do this. Why not share that in the comments?

29. December 2010 by joshfeck
Categories: Tutorials | 3 comments

Comments (3)

  1. Thank you very much for sharing this! This was exactly what I needed to build my custom page template!!

    I used Brad Williams’s Custom Post Type UI to build my custom post types. Then I used Custom Fields Template to build my admin side entry boxes. Then for the genesis_get_custom_field($arg, true); I had to make sure that my custom field names aligned though I like your custom method better. It was just easier to do it this other way so I could skip Devin Price’s step by step tutorial.

    Awesome post!!

  2. Is there a way to reverse the loop so the oldest appear first and the newest last?

  3. Yes, there is…to reverse the loop here simply change line 12 to:

    $loop = new WP_Query( array( 'post_type' => 'special', 'posts_per_page' => 20, 'order' => 'ASC' ) ); ?>

    Also as info, the genesis_get_custom_field only has one argument being passed. From options.php.
    function genesis_get_custom_field($field) {
    global $post;

    if ( null === $post ) return FALSE;

    $custom_field = get_post_meta($post->ID, $field, true);

    if ( $custom_field ) {
    // sanitize and return the value of the custom field
    return wp_kses_stripslashes( wp_kses_decode_entities( $custom_field ) );
    }
    else {
    // return FALSE if custom field is empty
    return FALSE;
    }
    }