Ladies Learning WordPress

Custom Post Types & Custom Fields


Wes Bos
@wesbos
WesBos.com

Wordpress is just for blogging, right?

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

Tonight's Schedule:

  1. Understand what custom post types are and how we can use them for creating new content.
  2. Create our recipes post type within WordPress
  3. Understand What custom fields are and how we can use them to create an interface for inputting our recipes
  4. Create a custom fields for our recipe post type
  5. Adapt our WordPress theme to create a listing of all recipes.
  6. Tinker Time

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!

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.

Permalinks

Remember Permalinks? Lets turn on pretty permalinks

Settings->permalinks

Exercise #1: 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:

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.

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

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

Exercise #2: Creating our custom fields

Again go to pluginsAdd 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 FieldsSettings → in the first input type
QJF7-L4IX-UCNP-RF2W

Creating the custom interface

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 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!

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.

If we just write "Hello there im the recipe page!" in our blank archive-recipes.php file and save it, we should see this:

Building the template to display recipes

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:


What template tags do we need?


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 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

<?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.

The Description

To get the entire description for the recipe, we use the template tag <?php the_content(); ?>


The Ingredients

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.

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

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

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

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

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 ); ?>

Overview

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

Questions?

Getting Help

http://wordpress.stackexchange.com/

#WordPress on freenode

WordPress forums

The codex is the most valuable thing in the world.