WordPress Toronto!

Custom Post Types & Custom Fields

Wes Bos

Wordpress is just for blogging, right?


Out of the box, WordPress is great for running a blog and powering static pages.

Behind the scenes, there is a great super powerful engine that allows you to create a full-featured content management system.

There are three parts of WordPress that we can use to create a totally custom CMS:

1. Custom Post Types

2. Custom Fields

3. Custom Taxonomies

We will be using #1 and #2 today

Tonight's Schedule:

  1. Understand what custom post types are and how we can use them for creating new content.
  2. Understand What custom fields are and how we can use them to create an interface for inputting our recipes
  3. Demo creating a custom backend
  4. Demo Adapting an existing theme

WordPress as a CMS!

I'm sure you have heard and seen it all..

Yah you can hack it

Make everything a post!

Nested categories from hell

Just add 1000 plugins!

Custom Post Types

Put simply, a post type in WordPress is a specific kind of content.

WordPress comes pre-installed with two primary post types: blog posts and pages.

But a post type can be pretty much any type of content!


Employee Listing





Books, Movies, Recipes...

Each Post type gets ability to edit just as if they were pages or blog posts.

Creating a custom post type

We are going to be creating a listing of recipes similar to what you might find on allrecipes.com or food.com

To do this, we need a new custom post type called recipe

To Create a new post type, one would usually use the <?php register_post_type( ) ?> function but there are 25 arguments with hundreds of different options.

Instead, we're going to use a development plugin called Custom Post Type UI which will give us a nice interface for creating the post type.

Log into your WordPress Dashboard and go to pluginsAdd New → search and install Custom Post Type UI

Registering the post type

Now that we have the plugin activated, we can go to Custom Post TypesAdd New

Advanced Options

We have the option to further customize the custom post type to take advantage of some of the many built in WordPress functionalities.

For example, we require comments, excerpt and categories for our recipes but a custom post type for quotes may just need the bare minimum.

1. Change Has Archive drop-down to true

2. Set the following:

Easy as that!

Thats it! Pretty easy, eh? You now have the recipes CPT in the sidebar:

Working with CPT

Custom post types work just like posts or pages.

They have archives, taxonomies, can be queried and so on

Custom Fields

You are probably asking yourself how WordPress can be a full CMS if we only have the title and body to input content into.

What happens if we want to have different fields associated with the post?

Custom fields are a great way to attach new inputs to your custom post type.

How many times have you put HTML into the WordPress box only to have a client delete it?

/me rage

Some Examples:

A start date and end date for an event

A file upload input for user downloads

Check box of pre-defined values, Input for a products price or tag line

Multiple WYSIWYG inputs for parts of the web page

Sexy inputs

There are a number of ways we can create custom inputs

Options Framework


Awesome for baking right into themes and plugins

Requires lots of extra coding

Pods CMS

Just got funded by Automattic

Version 1.0 created its own content types

Version 2.0 works with Custom Post Types

Seriously so awesome

Advanced Custom Fields

Currently the top dog and what I use daily

Custom Fields for our Recipes

By default, custom fields are plain text key and value inputs. Kind of a pain in the butt to work with!

We want a nice, usable interface so we're going to use another plugin called Advanced Custom Fields

Creating the custom interface

The First thing you need to do is create the interface.

Watch and learn!

Head on over to Custom FieldsAdd New to expose the custom field creation interface

At the top name it Recipes and set the Location rule to Post Type - is equal to - recipes

Click +Add Field and you'll see the interface for adding a new field. In the drop down you'll see all the types of field types that we can choose from!

For now we're only going to worry about the first three fields

Let's go ahead and add Prep Time, Cook Time and Total Time

For the list of ingredients and steps for preparation, we can't predict how many steps a recipe might have so we use a repeater field to allow the user to add as many as they wish.

So we create a field with the type of repeater and then within that we specify what the fields will be. In our case its just 1 field of 'step'

The steps field has 0 to n step fields

Rinse & Repeat by creating another field in the same way:

Ingredients with the type of repeater

You should now have 5 fields!

Now when we add a recipe we have a beautiful interface. Go ahead and add a few!

Other Input Types

Let's take a look at what other input types we can use


Awesome for when you don't know how many inputs your user needs

Flexible Content Fields

Does the user need an upload box for an image or a Google map picker?

Image / File Upload

Handy as heck!

Colour Picker

Various Selects

Dropdown, Checkbox, Radio, True/false

Custom Text Inputs

Full WYSIWYG, Textarea, textinput

Relationships and Post Object

Relate Posts to other posts.

Select associated recipes for a food type

Make your own!

Google map drop pin

Next Gen Gallery Selector

Now that we have all our recipes inputted, how do we get them to show up in our template?

When we go to <our blog url>/recipes we see a list of recipes, but only the title and body content. What gives?!

That is certainly not a good way to layout recipes and we aren't interested in having the sidebar in there either!

To make a custom layout, we need to edit the template files in our theme.

All of the files that control how our site looks are located in /wp-content/themes/llc-recipe

What file controls how the recipes are displayed?

WordPress has something called the Template Hierarchy where is specifies which files display the content.

By default, the listing of recipes will use archive.php - the same one is uses to display your blog.

We want to create our own so lets create a more specific one called archive-recipes.php which will override archive.php with our recipes custom post type.

Building the template to display recipes

Remember the Loop? The loop is a way to iterate over each recipe available and display the output on the page. Lets start with a simple template only showing the recipe title.

<?php get_header(); ?>
	<div class="full">
		<?php if(have_posts()) while(have_posts()) : the_post(); ?>
					<?php the_title(); ?>
		<?php endwhile; ?>
<?php get_footer(); ?>

See how when we save the page we now get our header, our footer and all the names of available recipes?

Lets expand on that and pull in all the fields we created with template tags. Our end result will look like this:

What template tags do we need?

Template Tags Refresher

Template tags help us easily output different parts of a recipe.

<?php the_title(); ?> - The recipe title

<?php the_excerpt(); ?> - Short version of the content

<?php the_post_thumbnail("recipe"); ?> - Gives us the post thumbnail sized for recipe

<?php the_category(", ") - Outputs the categories

Custom Field Template Tags

<?php the_field(" ");?>
<?php get_field(" ");?>
Outputs whatever custom field we pass it

What about the repeater field?

<?php while(the_repeater_field('ingredients')) : ?>

<?php the_sub_field('ingredient_name'); ?>

<?php endwhile; ?>

Looks great, but what happens when we click it to view the recipe?

We need to create a template for that too!

Right now its inheriting the single.php template that use use to display a single blog post.

To create a custom template for our recipes, we need to create a template file called single-recipes.php

We can re-use the code we created in archive-recipes.php so copy and paste everything into single-recipes.php

Looping through each ingredient

Since we aren't sure how many ingredients we have, we will use PHP's while loop to output them until we have none left.

The important template tags we are using here are:

the_repeater_field("ingredients"); - gets the high level field of "ingredients"

the_sub_field("ingredient"); - give us access to each individual ingredient when we are within our while loop

	<?php while(the_repeater_field('ingredients')) : ?>
		<li><?php the_sub_field('ingredient'); ?></li>
	<?php endwhile; ?>

The Steps

To get the same, repeat the same steps as we just did but replacing ingredients and ingredient with steps and step

Also note: we are using an ordered list in this case to number the steps

	<?php while(the_repeater_field('steps')) : ?>
			<li><?php the_sub_field('step'); ?></li>
	<?php endwhile; ?>				

Adding Comments

Finally, if you would like people to comment on you custom post type, its as easy as adding the following line below the final endwhile;

<?php comments_template( '', true ); ?>


WordPress lets you create custom post types to handle pretty much any type of content

We use custom fields to extend the interface and fields of that custom post type

With a little code and some new theme files, we can output and format both the custom post types and the custom fields in any way we want.

We used recipes as a simple example here but there are hundreds of different applications


Getting Help


#WordPress on freenode

WordPress forums

The codex is the most valuable thing in the world.