Custom Post Types & Custom Fields
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
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!
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!
Books, Movies, Recipes...
Each Post type gets ability to edit just as if they were pages or blog posts.
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
Add New → search and install
Custom Post Type UI
Now that we have the plugin activated, we can go to
Custom Post Types →
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:
Thats it! Pretty easy, eh? You now have the recipes CPT in the sidebar:
Custom post types work just like posts or pages.
They have archives, taxonomies, can be queried and so on
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.
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
There are a number of ways we can create custom inputs
Awesome for baking right into themes and plugins
Requires lots of extra coding
Just got funded by Automattic
Version 1.0 created its own content types
Version 2.0 works with Custom Post Types
Seriously so awesome
Currently the top dog and what I use daily
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
The First thing you need to do is create the interface.
Watch and learn!
Head on over to
Custom Fields →
Add 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 '
The steps field has 0 to n step fields
Rinse & Repeat by creating another field in the same way:
Ingredients with the type of
You should now have 5 fields!
Now when we add a recipe we have a beautiful interface. Go ahead and add a few!
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
Does the user need an upload box for an image or a Google map picker?
Handy as heck!
Dropdown, Checkbox, Radio, True/false
Full WYSIWYG, Textarea, textinput
Relate Posts to other posts.
Select associated recipes for a food type
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
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.
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; ?> </div> <?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:
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
<?php the_field(" ");?>
<?php get_field(" ");?>
Outputs whatever custom field we pass it
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
We can re-use the code we created in
archive-recipes.php so copy and paste everything into
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
<ul> <?php while(the_repeater_field('ingredients')) : ?> <li><?php the_sub_field('ingredient'); ?></li> <?php endwhile; ?> </ul>
To get the same, repeat the same steps as we just did but replacing
Also note: we are using an ordered list in this case to number the steps
<h3>Directions</h3> <ol> <?php while(the_repeater_field('steps')) : ?> <li><?php the_sub_field('step'); ?></li> <?php endwhile; ?> </ol>
Finally, if you would like people to comment on you custom post type, its as easy as adding the following line below the final
<?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
#WordPress on freenode
The codex is the most valuable thing in the world.