In a previous series, I provided an in-depth guide to working with the WordPress Settings API. For those who are new to WordPress or who have been using other tools such as The Customizer to handle various options, it may be something that you have not had to use in your theme or plugin development.
As stated in the Codex:
The Settings API, added in WordPress 2.7, allows admin pages containing settings forms to be managed semi-automatically. It lets you define settings pages, sections within those pages and fields within the sections.
I don't think it's something that's required to learn, but it's something that you should know exists and know how to work with it if you find yourself needing to introduce option pages into the WordPress administration area.
It's a powerful, albeit somewhat complex, API that provides us with a lot of functionality. Ultimately, it allows us to do a lot of work on the server side and minimal work on the client side.
But what about the times when we're working with a custom solution for clients and we need a little more flexibility than the Settings API provides? For example, say we need to build a plugin that will have a settings page but needs a more flexible set of options and tailored validation functionality?
In those cases, it's possible to write our own custom WordPress administration pages. In this series, we're going to take a look at how to do exactly that.
Before We Start
As with most tutorials like this, it's important to make sure that you have everything in place to follow along so that you can work with the source code that we cover throughout the series.
For this tutorial, I'm assuming:
- You have a local development environment setup relative to your operating system.
- You have a copy of WordPress installed and ready to be used for installing a plugin.
- You're familiar with WordPress plugin development practices.
- You're comfortable working with PHP and HTML.
If you're not familiar with how to set up a local development environment that includes WordPress, please see this series for how to do just that.
And if you're relatively comfortable with PHP, even if it's just reading the language, then I'll do the best I can to provide clear instructions and comments for each bit of code that we share.
Once all of this is in place, we're ready to begin working on our plugin.
Custom WordPress Administration Settings
By the end of this series, we're going to have a plugin that meets the following requirements:
- Adds a new submenu item to the existing WordPress menu system.
- Adds a new settings page that corresponds to the new submenu item.
- Sanitizes and serializes options on the page.
- Validates and returns the values that were saved and renders them accordingly.
Furthermore, we'll make sure that we approach this in the most modular way possible using the WordPress Coding Standards and similar practices to make reading, writing, and maintaining our plugin as easy as possible.
1. The Plugin Bootstrap
The first thing that we need to do is to create the plugin bootstrap. This will include creating a directory to house the plugin's files, a basic README, a copy of the license, a bootstrap file that will eventually be used to start the plugin, and a directory that will be used to hold the classes related to the administrative functionality.
The files are available for download as an attachment to this post but, in the meantime, you can see what my directory looks like below:
Furthermore, the contents of the plugin bootstrap are simple. Review the following code for the single PHP file custom-admin-settings.php
, and then I'll discuss it in more detail below the block.
<?php /** * The plugin bootstrap file * * This file is read by WordPress to generate the plugin information in the * plugin admin area. This file also defines a function that starts the plugin. * * @link http://code.tutsplus.com/tutorials/creating-custom-admin-pages-in-wordpress-1 * @since 1.0.0 * @package Custom_Admin_Settings * * @wordpress-plugin * Plugin Name: Custom Admin Settings * Plugin URI: http://code.tutsplus.com/tutorials/creating-custom-admin-pages-in-wordpress-1 * Description: Demonstrates how to write custom administration pages in WordPress. * Version: 1.0.0 * Author: Tom McFarlin * Author URI: https://tommcfarlin.com * License: GPL-2.0+ * License URI: http://www.gnu.org/licenses/gpl-2.0.txt */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } add_action( 'plugins_loaded', 'tutsplus_custom_admin_settings' ); /** * Starts the plugin. * * @since 1.0.0 */ function tutsplus_custom_admin_settings() { }
Notice that in the code above, there's actual very little code. Instead, it's a lot of comments. The main block of comments at the top of the file explains what the file does.
The area below the @wordpress-plugin
tag is what WordPress will read in order to generate the plugin's title, description, and relative links in the plugin dashboard of WordPress.
Next, we prevent anyone from accessing the file directly. And, finally, we create a custom function to be fired with the plugins_loaded
hook. This function is what will be used to start the plugin.
At this point, you should be able to log in to WordPress, navigate to the Plugin's Dashboard, and then see the plugin available to activate. Go ahead and click Activate.
Nothing will happen yet, but we'll start adding functionality as we work throughout this tutorial.
2. Creating the Submenu Item
In order to begin working on the plugin, let's first introduce a submenu item. To do this, we'll need to take advantage of the WordPress API function add_options_page
. This function will require five parameters:
- the text to display as the title of the corresponding options page
- the text to display as the submenu text for the menu item
- the capabilities needed to access this menu item
- the menu slug that's used to identify this submenu item
- a callback to a function that's responsible for rendering the admin page
Note that we'll be using classes to organize our functionality, so much of what we're doing is going to be object-oriented.
First, let's create a class in the admin directory called class-submenu.php
. Since this class is responsible for introducing a new submenu, we'll have it named descriptively.
The contents of the class should look like this:
<?php /** * Creates the submenu item for the plugin. * * @package Custom_Admin_Settings */ /** * Creates the submenu item for the plugin. * * Registers a new menu item under 'Tools' and uses the dependency passed into * the constructor in order to display the page corresponding to this menu item. * * @package Custom_Admin_Settings */ class Submenu { /** * A reference the class responsible for rendering the submenu page. * * @var Submenu_Page * @access private */ private $submenu_page; /** * Initializes all of the partial classes. * * @param Submenu_Page $submenu_page A reference to the class that renders the * page for the plugin. */ public function __construct( $submenu_page ) { $this->submenu_page = $submenu_page; } /** * Adds a submenu for this plugin to the 'Tools' menu. */ public function init() { add_action( 'admin_menu', array( $this, 'add_options_page' ) ); } /** * Creates the submenu item and calls on the Submenu Page object to render * the actual contents of the page. */ public function add_options_page() { add_options_page( 'Tuts+ Custom Administration Page', 'Custom Administration Page', 'manage_options', 'custom-admin-page', array( $this->submenu_page, 'render' ) ); } }
At this point, the plugin will still not do anything. We still need to create the actual Submenu_Page
class, and then we need to wire the classes up to the bootstrap file.
3. Creating the Submenu Page
Let's start with the Submenu_Page
class first. Create another file in the admin
directory and call it class-submenu-page.php
. Then, in the file, add the following code.
<?php /** * Creates the submenu page for the plugin. * * @package Custom_Admin_Settings */ /** * Creates the submenu page for the plugin. * * Provides the functionality necessary for rendering the page corresponding * to the submenu with which this page is associated. * * @package Custom_Admin_Settings */ class Submenu_Page { /** * This function renders the contents of the page associated with the Submenu * that invokes the render method. In the context of this plugin, this is the * Submenu class. */ public function render() { echo 'This is the basic submenu page.'; } }
When this page renders, it will simply display the text: "This is the basic submenu page." We'll eventually get into adding new options. But first, let's bring this plugin to life by instantiating it within our bootstrap file.
4. Rendering the Menu and the Page
Next, open the custom-admin-settings.php file that we created earlier in this tutorial. Let's go ahead and write the code necessary to introduce the new submenu item and its associated page.
Remember, the Submenu class requires that an instance of the Submenu_Page
class be passed into its constructor, and then we need to call the init method on the Submenu class to set the whole thing into motion.
In code, this looks like the following:
<?php // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } // Include the dependencies needed to instantiate the plugin. foreach ( glob( plugin_dir_path( __FILE__ ) . 'admin/*.php' ) as $file ) { include_once $file; } add_action( 'plugins_loaded', 'tutsplus_custom_admin_settings' ); /** * Starts the plugin. * * @since 1.0.0 */ function tutsplus_custom_admin_settings() { $plugin = new Submenu( new Submenu_Page() ); $plugin->init(); }
At this point, you should be able to refresh your installation of WordPress, activate the plugin (if it's not already activated), and then see your new page rendered within the administration area.
In the next article, we'll look at how we can begin introducing actual settings into the screen. Additionally, we'll look at some best practices in terms of working with our template and our template partials, and then we'll see how they will be wired up to the APIs responsible for not only saving them but how we will sanitize and validate them.
But before we go that far, I want to talk a little bit about the class design that we've seen in this tutorial. Generally speaking, I want to talk about why we have a class for the Submenu
and the Submenu_Page
and how it relates to the bootstrap file.
A Word on Class Responsibility
For those of you who are familiar with the Single Responsibility Principle, this section may not be of any interest to you. But if who need a refresher or want to hear more, then read on.
Gather together the things that change for the same reasons. Separate those things that change for different reasons.
There's more much to this, but if you were to look at each of our classes (at least the two we have thus far), then it's clear that the reasons our classes may change are as follows:
- The contents of the submenu may change. Anything from the page title to the menu slug and everything in between.
- The way the page renders its contents may (and will change). Specifically, right now it does nothing but echo a string. Soon, it will include a particular file. After that, it may need to include multiple files.
The above two reasons are two very different reasons that classes may change, so keeping them together in the same class would violate the above principle.
Ultimately, I bring this up not only to help shed light on greater software engineering principles that can be applied in WordPress, but also to help prepare you for some of the reasons we're going to be breaking apart certain things that are usually large files within the context of plugins.
The nice thing about learning principles is that they can be applied in multiple projects and not just in single projects. You learn them, you practice using them, and you get better at architecting solutions for other people.
The learning curve may be steep, but once you begin that uphill climb, it gets easier and easier to incorporate the principles into your day-to-day work. Then, the work you're providing for others becomes much easier to maintain over time.
Conclusion
Don't forget that you can download the plugin in its current state from this post. As we progress through the series, I'll make the latest version available on each post so you will be able to follow along with the code covered in each tutorial, tinker with it, and prepare questions that you may want to ask in the comments.
As a side note, if you're looking for other utilities to help you build out your growing set of tools for WordPress or for code to study and become more well-versed in WordPress, don't forget to see what we have available in Envato Market.
Remember, you can catch all of my courses and tutorials on my profile page, and you can follow me on my blog and/or Twitter at @tommcfarlin where I talk about various software development practices and how we can employ them in WordPress.
Finally, don't hesitate to leave any questions or comments in the feed below. I do my best to participate and answer every question or critique you offer as it relates to this project.
Comments