Advertisement
Theme Development

The Complete Guide To The WordPress Settings API, Part 3: All About Menus

by

At this point, we've learned why the Settings API matters, we've learned all about sections, fields, and settings, and we've even setup a Sandbox Theme that we're using to develop functionality as we explore the API.

In this article, we're going to take a look at how we can interface with the WordPress menu system. It's important to note that this isn't actually a part of the Settings API, but it's so closely related that we should familiarize ourselves with how to use it.

As our themes and/or plugins become more complex, we need to know all of the various ways that we can include them into the WordPress Dashboard. In this article, we're going to be taking a look at the various WordPress menu functions, when to use them, when to avoid them, and the situations to which each function lends itself best.


Understanding Menu Types

WordPress provides four different ways to include our own menus. Below, we'll take a look at each menu, the parameters each accepts, and code examples for how to use them throughout projects. We're aiming to develop a clear understanding of how the API works as it can lay a foundation for our future work.

Top-Level Menus

Menu pages refer to the menu items that you see when you first login to WordPress. That is, they are the available options in the left-hand menu that can contain a list of sub-menu pages.

All About Menus

To introduce your own menu page into the WordPress Dashboard, you use the add_menu_page function.

We'll take a look at a practical example in a moment, but first let's review the function - it accepts seven arguments (five required, two optional):

  • Page Title refers to the text that appears at the top of the browser window whenever the top-level menu page is displayed.
  • Menu Title is the text that appears in the actual menu. It's best to keep this somewhat short, otherwise it will wrap in the menu item and look a bit off against the rest of the menu items.
  • Capability refers to which users have access to the menu. This is simply a string value that represents one of the available roles.
  • Menu Slug is a unique identifier that you provide. It identifies this menu in the context of WordPress and also refers to the page that displays the options associated with this menu. It also provides a hook with which submenu items can register themselves.
  • Callback is the function that defines the content displayed on the page that corresponds to this menu. This can be inline HTML or refer to an external file.
  • Icon URL is the path to the icon that you want displayed next to the menu item in the WordPress menu. You can use one of WordPress' existing icons or use one of your own. This argument is optional.
  • Position defines the position where this menu will reside in the list of WordPress' menu items. By default, the menu appears at the bottom of the menu, but a custom position will place your menu above (or below) any of the existing WordPress menu items.

Let's take a look at an example. Locate functions.php in the WordPress Settings Sandbox and add the following two functions:

function sandbox_create_menu_page() {
}
add_action('admin_menu', 'sandbox_create_menu_page');

function sandbox_menu_page_display() { 
}

Note that we're using the admin_menu hook to register our menu item. This particular function fires right after the basic administration menu is in place so you want to register your menu here so that WordPress renders it while displaying the rest of the menus.

Next, let's setup the basic menu item. In keeping consistent with the articles earlier in this series, here is what we're planning to do:

  • Add a new menu to the bottom of the WordPress menu
  • We'll give it the name of our theme (that is, "Sandbox")
  • It will be available to all users
  • It will not include an icon

Easy enough, right? Let's go ahead and add our menu. Again, do not simply copy and paste this code. Read it, note the comments, and make sure that you fully understand what we're doing:

function sandbox_create_menu_page() {

	add_menu_page(
		'Sandbox Options',			// The title to be displayed on the corresponding page for this menu
		'Sandbox',					// The text to be displayed for this actual menu item
		'administrator',			// Which type of users can see this menu
		'sandbox',					// The unique ID - that is, the slug - for this menu item
		'sandbox_menu_page_display',// The name of the function to call when rendering the menu for this page
		''
	);

} // end sandbox_create_menu_page
add_action('admin_menu', 'sandbox_create_menu_page');

Now, refresh your WordPress administration menu and you should see a new menu item. When you click on it, you should see a blank page appear.

Obviously, this isn't very functional. Let's stub out the callback function we defined earlier in order to display something on the screen:

function sandbox_menu_page_display() {
	
	// Create a header in the default WordPress 'wrap' container
	$html = '<div class="wrap">';
		$html .= '<h2>Sandbox</h2>';
	$html .= '</div>';
	
	// Send the markup to the browser
	echo $html;
	
} // end sandbox_menu_page_display

The final version of your code should look something like this:

/**
 * Adds a new top-level menu to the bottom of the WordPress administration menu.
 */  
function sandbox_create_menu_page() {

	add_menu_page(
		'Sandbox Options',			// The title to be displayed on the corresponding page for this menu
		'Sandbox',					// The text to be displayed for this actual menu item
		'administrator',			// Which type of users can see this menu
		'sandbox',					// The unique ID - that is, the slug - for this menu item
		'sandbox_menu_page_display',// The name of the function to call when rendering the menu for this page
		''
	);

} // end sandbox_create_menu_page
add_action('admin_menu', 'sandbox_create_menu_page');

/**
 * Renders the basic display of the menu page for the theme.
 */
function sandbox_menu_page_display() {
	
	// Create a header in the default WordPress 'wrap' container
	$html = '<div class="wrap">';
		$html .= '<h2>Sandbox</h2>';
	$html .= '</div>';
	
	// Send the markup to the browser
	echo $html;
	
} // end sandbox_menu_page_display

Other than how to actually use the add_menu_page function, perhaps the most subtle take away is that, in WordPress, each menu item has a corresponding menu page. We'll take a look at this more in-depth throughout the series, but it's important to note now as we begin exploring each of the various types of menus.

Although this is largely incomplete, we'll be adding to this through out the rest of this article and the rest of the tutorial.

A Note on Positioning: Many developers consider using the position argument as bad etiquette as it mixes up the default user experience with WordPress. Additionally, if you define a position and another theme, plugin, or function uses the same position, one of the menu items can be overwritten.

Submenus

Submenus are just like menus with the exception that they belong to another menu - they have a parent. So, obviously, you can't create a submenu without creating a menu item first. Of course, like we saw in the last article, submenu items can be introduced to existing menu items - not just custom menu items.

In this article, we'll be introducing a submenu page into our own custom menu item. But before doing that, let's take a look at the add_submenu_page function and the parameters that it accepts:

  • Parent Slug refers to the ID of the parent menu item to which this submenu will belong. In our case, we'll use the menu slug that we defined above.
  • Page Title is the text that will appear in the browser title when the page is rendered.
  • Menu Title is the text that will appear as the actual menu item in the WordPress menu.
  • Capability, as with the parent menu, refers to what types of users have access to this particular menu.
  • Menu Slug is the unique identifier for this menu item. It's what is used to define this particular menu within the context of WordPress.
  • Callback is the function that is used to render this menu's page to the screen.

If you want to add a menu item to one of the existing menus, refer to table in the previous article.

Let's start by registering a submenu for the existing menu above. We want to do the following:

  • Register a submenu to be added to the menu we just created
  • It will display the text 'Options'
  • It will be available to all users
  • It will not include an icon

Check out the following code - we'll be adding this directly below our call to add_menu_page:

add_submenu_page(
	'sandbox',					// Register this submenu with the menu defined above
	'Sandbox Options',			// The text to the display in the browser when this menu item is active
	'Options',					// The text for this menu item
	'administrator',			// Which type of users can see this menu
	'sandbox_options',			// The unique ID - the slug - for this menu item
	'sandbox_options_display' 	// The function used to render the menu for this page to the screen
);

Don't forget to define the callback, even if it is empty. That is, don't forget to add this function to your file (we'll add more momentarily):

function sandbox_options_display() {	
} // end sandbox_options_display

When you refresh your browser, you should now see two submenu items directly below the "Sandbox" menu. Notice that WordPress creates a submenu item on its own - its a submenu item that corresponds to the menu item and the callback function defined. The second is the new submenu option that we just defined, though it renders no content.

To fix that, let's go ahead and introduce a basic page. Update the submenu's callback function to look like this:

function sandbox_options_display() {

	// Create a header in the default WordPress 'wrap' container
	$html = '<div class="wrap">';
		$html .= '<h2>Sandbox Options</h2>';
	$html .= '</div>';
	
	// Send the markup to the browser
	echo $html;
	
} // end sandbox_options_display

Refresh your browser once again and you should see a basic page title when you select the new Options submenu item.

Although this isn't required, note that you can actually have the parent menu item and the Options menu item refer to the same content - simply update the callback in the ad_menu_page function to the sandbox_options_display function that we just defined.


Plugin Pages

If you're developing a WordPress plugin, then there are a few different ways that your product may interface with the platform.

Specifically, your plugin...

  1. May work in the background and not require a menu.
  2. May use either both or one of functions mentioned above to build a custom menu
  3. May include itself in one of the existing WordPress menus

To make it easier for plugin developers to include their options in existing WordPress menus, the WordPress API offers the following function: add_plugins_page.

But wait. If you've been following along with the examples above, then you've likely noticed that there seems to be no discernible difference between add_plugins_page and add_submenu_page. You're right. add_plugins_page offers the same functionality as the add_submenu_page, but there are two primary differences:

  1. The plugin is provided specifically for use in plugin development.
  2. The function adds the plugins menu option directly to WordPress' Plugins menu.

Although you can certainly use add_submenu_page to achieve the same goal, I'm always a fan of using functions that are intended for a specific use case even if there is another API function that does the same. When you do this, you're showing that you're using the API as the developers intended and you're making your code a bit more cohesive as your codebase is more closely aligned with how it interacts with the core platform.

Plugin development is outside the scope of this particular series, but it's not completely irrelevant. Though there will be no modifications made to our Sandbox Theme, I do want to provide a simple example showing how to use this particular function.

First, let's review the arguments that add_plugins_page accepts:

  • Page Title is the text that will appear in the browser title when the plugin's option page is rendered.
  • Menu Title is the text that will appear as the plugin's menu item in the WordPress menu.
  • Capability as with the parent menu, refers to what types of users have access to this particular menu.
  • Menu Slug is the unique identifier for this menu item. It's what it used to define this particular menu within the context of WordPress.
  • Callback is the function that is used to render this menu's page to the screen.

Here's a simple example that demonstrates exactly how to use it. Note that you can include this in your functions.php file but it is not part of the Sandbox Theme that we're working on and should be used in the context of a plugin, instead.

First, setup the call to the API function - notice that this uses the admin_menu hook:

function sandbox_example_plugin_menu() {

	add_plugins_page(
		'Sandbox Plugin', 			// The title to be displayed in the browser window for this page.
		'Sandbox Plugin',			// The text to be displayed for this menu item
		'administrator',			// Which type of users can see this menu item
		'sandbox_plugin_options',	// The unique ID - that is, the slug - for this menu item
		'sandbox_plugin_display'	// The name of the function to call when rendering the page for this menu
	);

} // end sandbox_example_plugin_menu
add_action('admin_menu', 'sandbox_example_plugin_menu');

Next, setup the function that will render the plugin's display:

function sandbox_plugin_display() {

	// Create a header in the default WordPress 'wrap' container
	$html = '<div class="wrap">';
		$html .= '<h2>Sandbox Plugin Options</h2>';
		$html .= '<p class="description">There are currently no options. This is just for demo purposes.</p>';
	$html .= '</div>';
	
	// Send the markup to the browser
	echo $html;
	
} // end sandbox_plugin_display

Refresh your WordPress Dashboard, hover over the Plugins menu and you should notice a new menu item. Not bad, huh?

The final version of the code should look like this:

/**
 * This function introduces a single theme menu option into the WordPress 'Plugins'
 * menu.
 */
function sandbox_example_plugin_menu() {

	add_plugins_page(
		'Sandbox Plugin', 			// The title to be displayed in the browser window for this page.
		'Sandbox Plugin',			// The text to be displayed for this menu item
		'administrator',			// Which type of users can see this menu item
		'sandbox_plugin_options',	// The unique ID - that is, the slug - for this menu item
		'sandbox_plugin_display'	// The name of the function to call when rendering the page for this menu
	);

} // end sandbox_example_theme_menu
add_action('admin_menu', 'sandbox_example_plugin_menu');

/**
 * Renders a simple page to display for the theme menu defined above.
 */
function sandbox_plugin_display() {

	// Create a header in the default WordPress 'wrap' container
	$html = '<div class="wrap">';
		$html .= '<h2>Sandbox Plugin Options</h2>';
		$html .= '<p class="description">There are currently no options. This is just for demo purposes.</p>';
	$html .= '</div>';
	
	// Send the markup to the browser
	echo $html;
	
} // end sandbox_plugin_display

Again, this function will not be part of our Sandbox Theme because it's geared more towards plugin development; however, it is worth covering for those of you that will be leveraging the Settings API in your plugin development effort.

Theme Pages

Just as with plugins, WordPress provides an API function for introducing menus specifically for themes. It's very similar to the plugin menu function in that it provides yet another way to introduce a submenu to existing menus. The primary difference is that the submenu is added to the Appearance menu.

As with the plugin example earlier in this article, we'll take a look at how we can use this function but we won't be including it in our Sandbox Theme. This is meant purely to demonstrate how to use the function just in case you opt to go this route in your personal work.

First, we'll review the arguments that add_theme_page accepts. You'll notice that they are just like those required for the plugin menu and very similar to the submenu functions that we outlined earlier:

add_theme_page accepts the following arguments:

  • Page Title is the text that will appear in the browser title when the theme's option page is rendered.
  • Menu Title is the text that will appear as the theme's menu item in the WordPress menu.
  • Capability as with the parent menu, refers to what types of users have access to this particular menu.
  • Menu Slug is the unique identifier for this menu item. It's what it used to define this particular menu within the context of WordPress.
  • Callback is the function that is used to render this menu's page to the screen.

As with the other functions, we'll create a couple of sample functions that showcase to how include this in your project. Note that the call to add_theme_page can be added to functions.php and, unlike the calls to add_plugin_page, should reside here when developing your theme.

First, the call to setup the menu item:

function sandbox_example_theme_menu() {

	add_theme_page(
		'Sandbox Theme', 			// The title to be displayed in the browser window for this page.
		'Sandbox Theme',			// The text to be displayed for this menu item
		'administrator',			// Which type of users can see this menu item
		'sandbox_theme_options',	// The unique ID - that is, the slug - for this menu item
		'sandbox_theme_display'		// The name of the function to call when rendering the page for this menu
	);

} // end sandbox_example_theme_menu
add_action('admin_menu', 'sandbox_example_theme_menu');

Next, we'll setup a function to render the options page:

function sandbox_theme_display() {

	// Create a header in the default WordPress 'wrap' container
	$html = '<div class="wrap">';
		$html .= '<h2>Sandbox Theme Options</h2>';
		$html .= '<p class="description">There are currently no options. This is just for demo purposes.</p>';
	$html .= '</div>';
	
	// Send the markup to the browser
	echo $html;
	
} // end sandbox_theme_display

Now refresh the WordPress Dashboard, hover over the Appearance menu and you should see your new menu item. Simple!

The final version of the code should look like this:

/**
 * This function introduces a single theme menu option into the WordPress 'Appearance'
 * menu.
 */
function sandbox_example_theme_menu() {

	add_theme_page(
		'Sandbox Theme', 			// The title to be displayed in the browser window for this page.
		'Sandbox Theme',			// The text to be displayed for this menu item
		'administrator',			// Which type of users can see this menu item
		'sandbox_theme_options',	// The unique ID - that is, the slug - for this menu item
		'sandbox_theme_display'		// The name of the function to call when rendering the page for this menu
	);

} // end sandbox_example_theme_menu
add_action('admin_menu', 'sandbox_example_theme_menu');

/**
 * Renders a simple page to display for the theme menu defined above.
 */
function sandbox_theme_display() {

	// Create a header in the default WordPress 'wrap' container
	$html = '<div class="wrap">';
		$html .= '<h2>Sandbox Theme Options</h2>';
		$html .= '<p class="description">There are currently no options. This is just for demo purposes.</p>';
	$html .= '</div>';
	
	// Send the markup to the browser
	echo $html;
	
} // end sandbox_theme_display

For those of you that are interested in doing more advanced theme development, you've likely considered the various ways to implement multiple option pages for you theme.

On one hand, we can add multiple submenus to a top-level menu, but there is an alternative: tabbed navigation. This lends itself well when you want to introduce options to the Appearance menu and not add yet another menu item to the WordPress Dashboard. We'll be discussing this in more depth in the next article.


When to Use Each Function

We've taken a look at each of the four major ways to introduce our own option pages into WordPress. Though these functions aren't specifically part of the Settings API, it's important to discuss because they work so closely in conjunction with it.

But knowing these functions is only half of it. As a developer responsible for integration and organizing settings, it's important to know when to use each of the various functions in their proper context.

Though there's no silver bullet answer for when to use each function, here are some guidelines to consider when working on your custom functions, plugins, and/or theme:

  • Top-Level Menus can be added when there is a submenu that can be logically grouped with these options. This lends itself to when you have an important collection of settings that do not logically fit in any of the existing WordPress menus.
  • Submenus always belong to a top-level menu - either custom or pre-existing. They should always be grouped under the top-level menu that's most logical. If WordPress offers a menu that can serve as a parent for your submenu, then use it; don't pollute the menu with a redundant top-level menu.
  • Plugin Menus should be used when you have simple, one-page options for your plugin. If you have multiple option pages, consider creating a top-level menu or consider using tabbed navigation which we'll explore in the next article.
  • Theme Menus should be used when you are developing your own theme that offers its own set of custom options. If the options can live on a single page, consider using WordPress' API function. If you have more options, consider using tabbed navigation. Note that many theme developers often elevate their theme options to the top-level menu and that's okay, too.

A Word About Custom Menus: Although WordPress gives us the ability to add our own top-level menus, add to any existing menu, and generally gives us the ability to do what we want with the default configuration, a portion of the community frowns upon this. They believe that custom functionality should not interfere with certain core menus. Though it's ultimately up to you, implement your work with discernment - odds are, few things that you're doing are more important than WordPress core functionality, so don't place your work above that.


What's Up Next?

In the next article, we're going to apply a bit of what we've learned about menus and begin introducing option pages for our Sandbox Theme.

In addition to adding menu pages, we'll also take a look at tabbed navigation and how we can implement it to work in conjunction with our own menu pages.

In the mean time, review previous articles in this series and don't forget to checkout the current version of the WordPress Settings Sandbox on GitHub.


Related Resources

We covered quite a few resources in this article. Here's a summary of everything we used:

Related Posts