Ladies Learning WordPress
Custom Post Types & Custom Fields
Wes Bos
@wesbos
WesBos.com
Wes Bos
@wesbos
WesBos.com
Nope!
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
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!
Some Examples: Employees, Events, FAQs, Store Locations, Books, Movies
Each Post type gets ability to edit just as if they were pages or blog posts.
Remember Permalinks? Lets turn on pretty permalinks
Settings->permalinks
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 plugins → Add New → search and install Custom Post Type UI
Now that we have the plugin activated, we can go to Custom Post Types → Add New
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:
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.
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
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
Again go to plugins → Add New → search and install Advanced Custom Fields
You will now see the custom fields menu item in your sidebar
One last step before we're ready to go: In order to be able create repeatable groups of fields, we need to activate the repeater field.
This plugin is usually about $25 but the author has given us permission to use mine for the workshop!
Custom Fields → Settings → in the first input type QJF7-L4IX-UCNP-RF2W
So, what inputs do we need for a recipe?
We already have a spot for the title and the body of the recipe and we're able to use WordPress' featured image for the picture
For Each of the above, lets create a custom field.
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 '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!
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
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.
If we just write "Hello there im the recipe page!" in our blank archive-recipes.php file and save it, we should see this:
Remeber 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(); ?>
If this seems like a lot of code to type, feel free to copy and paste it off the slides.
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:
Lets start coding just below the line that look like this:
<?php if(have_posts()) while(have_posts()) : the_post(); ?>and end everything before the line that looks like this:
<?php endwhile; ?>
Everything between these lines will be repeated once for every recipe. Lets start with a wrapper div.
<div class="singleRecipe"> </div>
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(" ");?> - Outputs whatever custom field we pass it
Now we want to add the recipe picture and title as well as link them to the recipe.
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail("recipe"); ?>
</a>
<h2><a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a></h2>
Hows it looking? Lets add some more underneath that!
<?php the_excerpt(); ?>
<p><strong>Total Time: </strong>
<?php the_field("total_time"); ?></p>
<strong>Categories:</strong> <?php the_category(", "); ?>
See how we used <?php the_field("total_time"); ?> to grab our custom field from before?
If you also wanted prep time and cook time, you can add those as well replacing 'total_time' with 'prep_time' or 'cook_time'
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
Now we need to make a few changes.
1. Delete the_excerpt()
2. Add in 'prep_time' and 'cook_time' alongside 'total_time'
3. after </div> and before <?php endwhile; ?> we need to create a new div to hold our recipe details.
<div class="recipeDetails"> </div>
Now, inside our new div we want to have three things: The description, the ingredents, and the steps.
To get the entire description for the recipe, we use the template tag <?php the_content(); ?>
Let's use h3 tags to make the heading and then create an unordered list which will hold list all ingredients.
<h3>Ingredients</h3> <ul> </ul>
Finally, inside our unordered list, we will use template tags to spit out each of the ingredients.
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
<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 ingredients and ingredient with steps and step
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 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
http://wordpress.stackexchange.com/
#WordPress on freenode
WordPress forums
The codex is the most valuable thing in the world.