How to Create a Restaurant Menu in Wordpress 3 using Custom Post Types and Taxonomies
Published Wednesday 18th of January 2012
I recently created a restaurant website in Wordpress and for the first time got to use Wordpress 3's new "Custom Post Types" feature. Here I thought I'd explain how you too can create a menu using the same.
We'll create a menu where each dish has a title, picture, description and price. Each dish will also be grouped under a category like "Meat" or "Fish".
First, we'll create our new post type for our dishes. Put this in your theme's functions.php file:
<?php
register_post_type('dishes', array(
'label' => __('Dishes'),
'singular_label' => __('Dish'),
'public' => true,
'show_ui' => true,
'capability_type' => 'post',
'hierarchical' => false,
'query_var' => false,
'supports' => array(
'title',
'editor',
'excerpt',
'thumbnail',
'author',
'page-attributes'
)
));
Refer to the Wordpress Codex if you're curious about all the options.
That's all that's needed for a new menu item to show up in the admin; "Dishes". You could use "custom-fields" for the price but I think it's easier for the admin if we use the excerpt instead.
Now let's create a custom taxonomy for grouping our dishes:
<?php
register_taxonomy('dish_types', 'dishes', array(
'label' => __('Dish Type'),
'hierarchical' => true
));
That's it. Now when you add a new "Dish" you'll get to choose from your "Dish Types". Go ahead and add some new "Dish Types" and then add a couple of "Dishes" to each type.
Now we have everything we need in the admin / backend. All that's left is to display the menu on our website. We'll create a custom template for our menu called "menu.php". You can make it a copy of "page.php" so that the admin can still add text to the menu page. You need to set the "Template Name"-comment in the top of the file for Wordpress to recognize our new template:
<?php /* Template Name: Menu */ ?>
No let's write the code we need to fetch all our dish types as well as dishes. This code goes in the previously created menu.php, below the page-specific stuff:
<section id="menu">
<?php $types = get_terms('dish_types', array('orderby' => 'id')) ?>
<?php foreach ($types as $type) : ?>
<h3><?php echo htmlspecialchars($type->name) ?></h3>
<?php if ($type->description) : ?>
<p><?php echo htmlspecialchars($type->description) ?></p>
<?php endif ?>
<?php $dishes = get_posts(array('post_type' => 'dishes', 'dish_types' => $type->slug)) ?>
<ul>
<?php foreach ($dishes as $post) : setup_postdata($post) ?>
<li>
<h4><?php the_title() ?></h4>
<?php the_post_thumbnail() ?>
<p class="price"><strong><?php the_excerpt() ?></strong></p>
<?php the_content() ?>
</li>
<?php endforeach; wp_reset_postdata() ?>
</ul>
<?php endforeach ?>
</section>
The code should hopefully be pretty self explanatory. The meat of it is first the call to get_terms() which retrieves all the terms for a taxonomy and get_posts() which is used to retrieve any post type based on params.
As you can see I use the_excerpt() to store the price of the dish. If you'd rather use a custom fields called "Price" you would display it like this: echo get_post_meta($post->ID, 'Price', true).
Happy Wordpressing!
- Tags
- Comments
- 6 comments
Comments
Published Monday 6th of February 2012
Hi there,
Very helpful tutorial.
It all makes sense up until the very last bit of code. I'm afraid it's not quite 'self-explanatory'... Where does it go? Does it go into the new menu.php template or somewhere else?
Published Tuesday 7th of February 2012
@kamera - The last bit of code should be put in the menu.php-file (the "Menu" template).
Put it all beneath the normal "page" code so that it looks something like this (very simplified):
<?php /* Template Name: Menu */ ?>
<?php get_header() ?>
<h2><?php the_title() ?></h2>
<?php the_content() ?>
# Menu code goes here
<?php get_sidebar() ?>
<?php get_footer() ?>
Published Tuesday 7th of February 2012
@kamera - I've also changed this part:
<?php $dishes = get_posts(array('post_type' => 'dishes', 'dish_types' => $type->name)) ?>To:
<?php $dishes = get_posts(array('post_type' => 'dishes', 'dish_types' => $type->slug)) ?>The change being
$type->nameto$type->slug.Published Tuesday 14th of February 2012
This is exactly what I need, thanks! I apologize for my ignorance, but say I need to have a parent page of Menu, with subpages for Appetizers, Soups, Salads, etc.
I imagine I'll need to create a template for each one, but I can't figure out how to call one dish type per page. Maybe by the slug? One example would be greatly appreciated. Thanks again!
Published Tuesday 14th of February 2012
@Jeremy - That's a little out of the scope of this article, but I think you should be able to create an
archive-dishes.php-template which would be used for all archive-pages of dishes. That way you should be able to view just one category (dish_type) of dishes on each URL.If not, you could do what I do in the tutorial but hide/show the different dish-type-sections using JS. If there's less than say 200 dishes I think that would be the best solution actually.
It would be easy to do as well, just wrap every dish-type in an element with a unique ID (id="dish-type-<?php echo $type-ID ?>") and then use a tabs plugin for jQuery.
Published Tuesday 14th of February 2012
Thanks AL!