Creating a Restaurant Menu with WordPress and Advanced Custom Fields
A must-have plugin for every WordPress site, Advanced Custom Fields can be configured to build a customizable, easy to manage restaurant menu system. Here's how.
Published On: May 12th, 2020
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
Warning: Undefined array key "ssba_bar_buttons" in /home/seanpatr/public_html/wp-content/plugins/simple-share-buttons-adder/php/class-buttons.php on line 598
With WordPress, it’s a good policy to keep your plugin use to a minimum. Plugins tend to be bloated, cause conflicts, and, when you use them, you are completely at the whim of the developer when it comes to updates/fixes/improvements/support. Not to mention, they can bring about some serious security risks.
Therefore, I (like most in the WordPress world) cannot recommend Advanced Custom Fields (“ACF”) enough. Advanced Custom Fields is a developers dream because it is trusted and can do the jobs of many plugins with just one.
The project in this tutorial was for a long-time pizza shop client. When we first built their website in 2012, we used a popular plugin to handle their food menu, but over time, the plugin was abandoned by its developers and lost compatibility with newer versions of WordPress. To prevent this from happening again, I decided to build a own menu system using ACF Pro*. The results: A menu that looks identical to the old one on the front-end, but that’s easier to manage and has tons of flexibility for the client.
Want to do it yourself? Here are the steps:
1. Planning
First, we need to know what we’re going to display on our menu pages. In this case, we want the following:
Page Title
Page Description
Section Name
Section Description
Item Name
Item Price
Item Description
Next, let’s get some design inspiration. I will be working off of the design established via the former plugin, so I decided to mimic it. Below is a screenshot of that design with some notations on how things will be divided into HTML elements.
With a good idea of what will be displayed and how to display it, let’s put together a structure tree that will help us execute the plan. Remember that we’re working with multiple locations, each with different menus at each location. Therefore, we’ll be using two pages.
Here’s an overall look at what we’ll be creating:
Location One (Page)
Page Description
Menu Section
Section Description
Item Name
Price
Item Description
Location Two (Page)
Page Description
Menu Section
Section Description
Item Name
Price
Item Description
Before we get on to the next steps, let’s make sure we’re starting from the same point by completing the following:
Login to your WordPress admin
Install the Advanced Custom Fields Pro plugin (and activate it)
Create a new Page called “Location #1” and publish it blank.
2. Create the Fields
In the WordPress admin area, click on the “Custom Fields” link on the main menu to go to the ACF main page.
Click the “Add New” button to create a new Field Group.
Field Set Title: Location #1
Click the “Add Field” button to create a field for each restaurant location’s contact information:
Field Label: Page Description
Field Name: page_description
Field Type: Text Area
Click the “Add Field” box and add a new Field called “Section” (Field Name: “section”)
Field Name: section
Field Type: Repeater
Layout: Block
In the “Sub Fields” box, add the following:
Section Name
Field Name: section_name
Field Type: Text
Note that in this tutorial, no fields will be required. In this case, making something required would just decrease our flexibility.
Section Description
Field Name: section_description
Field Type: Text
You can limit the the character count if it benefits your design. In this case, it does not.
Item
Field Name: section_description
Field Type: Text
Sub-Fields:
Item Name
Field Name: item_name
Field Type: Text
Item Description
Field Name: item_description
Field Type: Text
Item Price
Field Name: item_price
Field Type: Text
In the “Location” box below the Fields, applies the Field Group to Page > Is Equal To > Location #1
In the “Settings” box below “Location”, scroll down to “Hide on Page” and uncheck the box next to “Content Editor” – we won’t be needing it so let’s hide it to keep the back-end tidy.
Publish the Field Group.
3. Add the Theme Page
Open your WordPress theme in a text editor
Create a new file within your theme directory, name it ‘menu.php’
First, we need to designate this file as a new template for a WordPress page, so we’ll put this at the top.:
<?php
/*
* Template Name: Menu Page
* Template Post Type: page
*/
get_header(); ?>
This creates a new Page Template called ‘Menu Page’ that we can use for our menus. Also, by including the ‘get_header();’ command, the page will be hooked into your theme’s header, which should include navigation menu, stylesheets, etc. If you’re unsure what this is all about, check out Page Templates in the WordPress Theme Handbook
Next, we’ll get the menu page started with a section that will include the page title and page description. While we’re at it, we’ll wrap the entire page in a class that will help with styling later. We’ll also open and close the WordPress loop so that we can access this page’s information:
<div class="menuPage"> <!-- Wrapping the page in a menuPage class -->
<!-- This code opens the WordPress loop so that we can work with the information from the page manager. -->
<?php if(have_posts()) : ?><?php while(have_posts()) : the_post(); ?>
<div class="title">
<h1><?php the_title(); ?></h1> <!-- Adds the Page Title -->
<p>
<!-- This is our first ACF code. It says that if there is anything in the page_description field, it will go here. Since it's wrapped in <div class="title><p>, it will take on that styling -->
<?php if( get_field('page_description') ): ?>
<?php the_field('page_description'); ?>
<?php endif; ?>
</p>
</div>
<!-- The code below closes the WordPress Loop -->
<?php endwhile; ?>
<?php endif; ?>
</div>
Now that the title area is in place, let’s start the menu. This is a bit more complicated:
<div class="menuBody">
<!-- Start by checking if there are any Sections -->
<?php if( have_rows('section') ): ?>
<!-- If there are, we return the following for each -->
<?php while( have_rows('section') ): the_row(); ?>
<div class="menuSection">
<h2>
<?php the_sub_field('section_name'); ?>
</h2>
<h4>
<?php if( get_sub_field('section_description') ): ?> // We'll put an 'if' statement here since some sections may not have a description
<?php the_sub_field('section_description'); ?> // ...But if they do, it'll appear.
<?php endif; ?>
</h4>
<!-- This 'if' statement checks if any Items are present... -->
<?php if( have_rows('item') ): ?>
<!-- ...and returns the following list with each instance of Item appearing as an <li> -->
<ul>
<?php while( have_rows('item') ): the_row(); ?>
<li class="menuItem">
<div class="itemTop">
<h3>
<?php if( get_sub_field('name') ): ?>
<?php the_sub_field('name'); ?>
<?php endif; ?>
</h3>
<p class="itemPrice">
<?php if( get_sub_field('price') ): ?> // If statement here in case we want to keep the price off a certain item
<?php the_sub_field('price'); ?>
<?php endif; ?>
</p>
</div>
<p>
<?php if( get_sub_field('description') ): ?> // If statement in case item does not need description
<?php the_sub_field('description'); ?>
<?php endif; ?>
</p>
</li>
<!-- This code closes out the Items list -->
<?php endwhile; ?>
</ul>
<?php endif; ?>
</div>
<!-- This code closes out the rest -->
<?php endwhile; ?>
<?php endif; ?>
</div>
Finally, to wire in our existing Footer, close the page with:
All together, our new menu.php page will look like this:
<?php
/*
* Template Name: Menu Page
* Template Post Type: page
*/
get_header(); ?>
<div class="menuPage"> <!-- Wrapping the page in a menuPage class -->
<!-- This code opens the WordPress loop so that we can work with the information from the page manager. -->
<?php if(have_posts()) : ?><?php while(have_posts()) : the_post(); ?>
<div class="title">
<h1><?php the_title(); ?></h1> <!-- Adds the Page Title -->
<p>
<!-- This is our first ACF code. It says that if there is anything in the page_description field, it will go here. Since it's wrapped in <div class="title><p>, it will take on that styling -->
<?php if( get_field('page_description') ): ?>
<?php the_field('page_description'); ?>
<?php endif; ?>
</p>
</div>
<div class="menuBody">
<!-- Start by checking if there are any Sections -->
<?php if( have_rows('section') ): ?>
<!-- If there are, we return the following for each -->
<?php while( have_rows('section') ): the_row(); ?>
<div class="menuSection">
<h2>
<?php the_sub_field('section_name'); ?>
</h2>
<h4>
<?php if( get_sub_field('section_description') ): ?> // We'll put an 'if' statement here since some sections may not have a description
<?php the_sub_field('section_description'); ?> // ...But if they do, it'll appear.
<?php endif; ?>
</h4>
<!-- This 'if' statement checks if any Items are present... -->
<?php if( have_rows('item') ): ?>
<!-- ...and returns the following list with each instance of Item appearing as an <li> -->
<ul>
<?php while( have_rows('item') ): the_row(); ?>
<li class="menuItem">
<div class="itemTop">
<h3>
<?php the_sub_field('name'); ?>
</h3>
<p class="price">
<?php if( get_sub_field('price') ): ?> // If statement here in case we want to keep the price off a certain item
<?php the_sub_field('price'); ?>
<?php endif; ?>
</p>
</div>
<p>
<?php if( get_sub_field('description') ): ?> // If statement in case item does not need description
<?php the_sub_field('description'); ?>
<?php endif; ?>
</p>
</li>
<!-- This code closes out the Items list -->
<?php endwhile; ?>
</ul>
<?php endif; ?>
</div>
<!-- This code closes out the rest -->
<?php endwhile; ?>
<?php endif; ?>
</div>
<!-- The code below closes the WordPress Loop -->
<?php endwhile; ?>
<?php endif; ?>
</div>
<?php get_footer(); ?>
4. Style It
With that, we have our structure in place, so let’s jump back to the WordPress admin to add some content and see if things are working correctly. In the WordPress admin area, return back to the Location #1 page. A reminder that, at this point, it should look like this:
Let’s add some content. First, a page description. The good news is that ACF Text Fields accept HTML, so we’ll inject a bit for fancy styling. Add the following code into the text box for Page Description:
<p class="intro">Items are available for dine-in, pick up, and delivery (within a 5 mile radius).<br>
Call <a href="tel:XXXXXXXXXX">[PHONE NUMBER]</a> to order now</p>
This will allow to give the “intro” class some styling later and include a link so customers can easily tap to call and place their order.
Next up, let’s add a few items:
Under Section, click the ‘Add Row’ button to add a new Section:
Section Name: Pizzas
Section Description: Our fresh dough made on premises daily with your choice of RED, WHITE, or PINK sauce. Pizzas are available in Thin, Orginal or Extra Thick crusts. Half toppings are available for half the listed price.
Within the new ‘Pizzas’ Section, click the ‘Add Row’ button to add our first menu item:
Item Name: Large 18” Pizza
Item Price: $18.99
Item Description: 12 slices (feeds 5-6)
Following the same process, add the following items:
Item Name: Medium 14” Pizza
Item Price: $15.99
Item Description: 8 slices (feeds 3-4)
Item Name: Small 10” Pizza
Item Price: $12.99
Item Description: 4 slices (feeds 1-2)
Finally, we’ll add a second section called Specialty Pizzas following the same process with the information below:
Item Name: Buffalo Chicken Pizza
Item Price: Large $19.99 | Medium $15.99 | Small $13.99
Item Description: Buffalo sauce with grilled chicken, bleu cheese, and mozzarella
Item Name: Meat Lovers
Item Price: Large $19.99 | Medium $15.99 | Small $13.99
Item Description: Sausage, pepperoni, bacon, and ham
In the WordPress admin area, create a new page called “Locaiton #2” and publish it.
Go to the ACF Field Groups Page, click on the Location #1 field group to open it.
Since we’ll be using this for more than just Location #1, let’s change the name to ‘Food Menu’
In the ‘Location’ box, click the ‘Add Rule Group’ button.
In the new rule group, set the Field Group equal to: Page > is equal to > Location #2
Alternately, you may delete the original Location #1 rule, and create a new rule that applies the Field Group to the Template called “Menu Page”
Was this tutorial helpful to you? Do you have any tips to make it better? Did I make a (gasp!) mistake? I love to hear feedback of all sorts, so click here to Contact Me.