- Key Takeaways
- Planning the Finished Product
- Making a Start
- Adding the Options page
- Building the Options Page
- Register the Settings
- Adding the Fields
- Rendering the Inputs
- Retrieving Option Values
- Styling the Options Page
- Adding More Options
- Uploading Files
- Conclusion
- Frequently Asked Questions (FAQs) about WordPress Options Panel
Out with the old; in with the new. Not too long ago, the process of creating an Options page for a WordPress theme was a bit of a nightmare. Sure, it was relatively easy to do once you’d wrapped your head around the process, but, it required an extensive amount of work, including writing security checks, creating the forms, manually adding hidden inputs, and so on.
Luckily, as of WordPress 2.7, the process has been streamlined, thanks to the new Settings API. In this tutorial, Jeffrey Way, author of Build Your Own Wicked WordPress Themes demonstrates exactly how to build an Options page from scratch. He also included a video version of this tutorial for those who prefer a more visual approach. You’ve no doubt seen a number of these sorts of articles around the web, but this will make the process as understandable as possible—particularly for those of you who are just getting started! Let’s begin.
Key Takeaways
- Utilize the WordPress Settings API introduced in version 2.7 to streamline the creation of custom Options pages, reducing the need for extensive manual coding.
- Begin by planning the desired features and appearance of your Options page, ensuring it meets your specific needs for theme customization.
- Store your Options page code within a separate PHP file in your theme’s `functions` folder to maintain clean and organized code.
- Use the `add_options_page` function combined with the `admin_menu` hook to add your custom Options page to the WordPress dashboard.
- Implement the `register_setting` and `add_settings_section` functions to organize and register your settings securely in the WordPress database.
- Retrieve and utilize the stored options in your theme using the `get_option` function, allowing dynamic customization based on user input.
Planning the Finished Product
First up, let’s organize our thoughts a bit, and determine exactly what we want our final product to look like and do.
This Options page should allow us to upload images, add text, and perhaps choose color schemes. Figure 1, “The finished Options page” shows what we’d like our Options page to look like by the time we’re done.
Once a user has entered values into this form, we can retrieve them from within our theme template files using the helpful get_option
method, like so:
<?php $options = get_option('plugin_options'); ?><h2><?php echo $options['banner_heading']; ?></h2>
In accordance with the value entered in Figure 1, “The finished Options page”, this will render “Buy Me.” Pretty convenient, right? Okay, let’s build this thing.
plugins
folder, or we can make it a theme-specific Options page, and store it within our theme’s functions.php
file (or another file included from functions.php
). In this case, we’ll go with the latter solution, though either approach will work.As functions.php
will store a variety of functions for your theme, it’s best to keep your Options page in its own file, which we can then include from functions.php
. Start by creating a folder called functions
within your theme folder. In this folder, create a new file called admin-menu.php
. Next, we need to make this page visible from our core functions file. Return to functions.php
, and include this file like so:
Example 1.
(excerpt)theme
/functions.php
<?php require_once(TEMPLATEPATH . '/functions/admin-menu.php'); ?>
As TEMPLATEPATH
will automatically generate the path to your theme folder, we need only continue the path to admin-menu.php
.
Next, we must tell WordPress to add a new Options page to the WordPress dashboard. Conveniently, WordPress provides the useful add_options_page
function. However, we can’t immediately call this method—we have to register the function with the admin_menu
hook first:
Example 2.
(excerpt)theme
/functions/admin-menu.php
add_action('admin_menu', 'create_theme_options_page');function create_theme_options_page() { add_options_page('Theme Options', 'Theme Options', 'administrator', __FILE__, 'build_options_page');}
The code above instructs WordPress to call the create_theme_options_page
function, which adds the page to the Settings section of the WordPress dashboard. The add_options_page
function requires a handful of parameters:
$page_title
: the title of the page$menu_title
: the name of the menu$access_privileges
: who has permission to access this page$page_name
: can be a unique string, but many developers prefer to use__FILE__
to ensure that the name is unique, and doesn’t have the potential to clash with any other pages$callback
: the function that will handle the creation of the options form
Let’s break this down. We’re essentially saying, “Add a new page to the Settings section of the dashboard, use these values for the title and access privileges, and then call the build_options_page
function to handle the creation of the page.”
Figure 2, “The Theme Options link in the WordPress dashboard” shows the link output in the Settings section of the WordPress dashboard menu.
We’ve called the build_options_page
function; now we need to create it:
Example 3.
(excerpt)theme
/functions/admin-menu.php
function build_options_page() {?> <div id="theme-options-wrap"> <div class="icon32" id="icon-tools"> <br /> </div> <h2>My Theme Options</h2> <p>Take control of your theme, by overriding the default settings with your own specific preferences.</p> <form method="post" action="options.php"> <p class="submit"> <input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes'); ?>" /> </p> </form> </div><?php}
This should be familiar to you, except perhaps for a couple points:
The
div
with aclass
oficon32
is used to add that little icon. WordPress has a variety of icons that it uses for various pages; we’re just borrowing this one for our custom page.By default, WordPress dashboard buttons are grey. By applying a
class
ofbutton-primary
, for which WordPress has already written styling, we can make the button blue, and have it “pop” a bit more.We use
esc_attr_e('Save Changes')
as the value for the Submit button. We use the translation function to ensure that this text can be localized.
Remember, when possible, to always use WordPress’s built-in classes. This makes your pages more consistent with the visuals of the dashboard.
You must have noticed that—somewhat strangely, perhaps—we didn’t add any inputs to our form. If we were using the old method, we would have done so; however, with the Settings API, the process works a bit differently.
We need to register our new option in the database using the register_setting
function. But before we can do that, we must again listen for the admin_init
hook. The admin_init
hook is triggered when you access the dashboard. This is the point when we need to register our option settings. As the second parameter, we’ll pass a callback function name that will handle the process of registering our settings:
Example 4.
(excerpt)theme
/functions/admin-menu.php
add_action('admin_init', 'register_and_build_fields');function register_and_build_fields() { register_setting('plugin_options', 'plugin_options', 'validate_setting');}
This register_setting
function accepts three parameters:
$option_group
: a string representing the name of the settings group$option_name
: the name of the option$sanitize_callback
: a callback function that can handle any specific operations or sanitizing
By registering this plugin_options
setting, we can then ultimately access its stored values using this code:
$options = get_option('plugin_options');echo $options['value'];
Since we’ve specified validate_setting
as the callback function, we need to define it. Our callback function needs to accept the $plugin_options
variable, and return it when it’s finished validating or sanitizing:
Example 5.
(excerpt)theme
/functions/admin-menu.php
function validate_setting($plugin_options) { return $plugin_options;}
We’ll be doing more with this function in the next example.
Next, we need to use the add_settings_section
method, which allows us to create sections—groups of like items—on our Options page. Sections let us organize the information that’s displayed, to make it more usable. You can create multiple sections should your project need them, but in most cases, one will do just fine. So let’s append the following code to our register_and_build_fields
function:
Example 6.
(excerpt)theme
/functions/admin-menu.php
add_settings_section('main_section', 'Main Settings', 'section_cb', __FILE__);
This function can accept four parameters:
$id
: a unique ID for the section$title
: a heading that will be displayed above the fields on the page$callback
: can handle the creation of the section; if it’s declared, you must create the function, or an error will be thrown$page
: defines the type of settings page that this section should be applied to; in our case, it should apply to our custom page, so we used__FILE__
as the name
To avoid throwing an error, we need to define the callback function we just set. It’s simple:
The next step is to add the fields, or the inputs, for our Options page using the add_settings_field
function. Let’s start with the banner_heading
field. The following code can again be appended to the register_and_build_fields
function:
Example 8.
(excerpt)theme
/functions/admin-menu.php
add_settings_field('banner_heading', 'Banner Heading:', 'banner_heading_setting', __FILE__, 'main_section');
We can pass a total of six arguments to this function, though we’ll only use five in this application:
$id
: a unique ID for the attribute$title
: the title of the field; this will essentially be the label for the input$callback
: handles the creation of the input; from this function, we’ll echo out the necessary HTML$page
: the type of settings page to which this section should be applied; again, in this case, we use__FILE__
as the name$section
: the name of the section to which this field relates; we called oursmain_section
$args
(optional): any additional arguments, passed as an array
With this code, we’ve added a new settings field, and have declared banner_heading_section
as the callback function that will handle the creation of the input. We can build that function now:
Example 9.
(excerpt)theme
/functions/admin-menu.php
// Banner Headingfunction banner_heading_setting() { $options = get_option('plugin_options'); echo "<input name='plugin_options[banner_heading]' type='text' value='{$options['banner_heading']}' />";}
This code requires a bit of explanation. In its simplest form, the function echo
s out a textbox. We’ve given this input the name plugin_options[banner_heading]
, to allow us to add a new key to the plugin_options
setting that we registered previously. Lastly, these inputs won’t always be blank. To remind the administrator which values are currently set in each option, we use the value
attribute of the textbox to display the current value of this particular option.
We’ve successfully registered our plugin_options
setting, and we’ve added a new field. Next, we must return to our form and designate where we want to insert each field, or input. Return to the build_options_page
function, and modify the form like so:
Example 10.
(excerpt)theme
/functions/admin-menu.php
<form method="post" action="options.php" enctype="multipart/form-data"> <?php settings_fields('plugin_options'); ?> <?php do_settings_sections(__FILE__); ?> <p class="submit"> <input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes'); ?>" /> </p></form>
Notice that we’ve added two new functions:
settings_fields
: This extremely helpful function will echo out all of the hidden fields for us, increasing the security of our plugin. Before the Settings API existed, we had to do this manually. This function accepts one parameter: theoption_group
name that was specified in theregister_setting
function. We called oursplugin_options
.do_settings_sections
: This function cycles through all of the fields that we’ve created (only one so far) and displays the inputs accordingly. It also accepts one parameter, which should be equal to the unique page ID for our Options page.
If you return to the WordPress dashboard and click on the Figure 4, “Our new banner heading option”.
page, you’ll see a form field for the banner heading, as shown inThe textbox from the image above is blank because we haven’t yet set a value for the banner_heading
option. As soon as we enter a value, click , and refresh the page, it’ll display the current value of the option within the database.
Believe it or not, you now have a working Options page! It only has one option, but now, the process of adding more is amazingly simple. So let’s imagine that we applied a value of “My Awesome Banner Heading” to the plugin_options[banner_heading]
field above. Your question might now be, “How do I retrieve this value in my theme?” Easy.
Anywhere within your theme template files, add this code:
1<?php $options = get_option('plugin_options'); ?><h2> <?php echo $options['banner_heading']; ?> </h2>
This code will output an h2
element, as shown in Figure 5, “Displaying the banner heading”.
Our Options page works just fine in its current form, but let’s style it just a tad. To do so, we can use a mixture of WordPress’s native class
es, as well as some of our own CSS. To reference a stylesheet from the Options page, we must listen for the admin_head
hook—this action will run when the head
section for the dashboard is created. This is where we’ll insert our stylesheet reference as follows:
Example 11.
(excerpt)theme
/functions/admin-menu.php
// Add stylesheetadd_action('admin_head', 'admin_register_head');function admin_register_head() { $url = get_bloginfo('template_directory') . '/functions/options_page.css'; echo "<link rel='stylesheet' href='$url' />n";}
admin_register_head
is the callback function that will handle the creation of our stylesheet. Assuming that we’ve added a new options-page.css
stylesheet to the functions
folder, we can echo out a link tag that points to that file.
Before we begin to edit our newly created stylesheet, let’s add to our page a few classes for which WordPress has, handily, already written the styling. Return to the build_options_page
function, and add a class
of widefat
to the theme-options-page
div
:
The form will now appear as shown in Figure 6, “The display after we add the widefat class”.
This helps a bit by adding some borders; however, it still needs work. In the new options-page.css
file that we just created, add the following:
Example 13. theme
/functions/options-page.css
#theme-options-wrap { width: 700px; padding: 3em; background: white; background: -moz-linear-gradient(top, #f4f2f2, white 20%, #f4f2f2 80%, white); background: -webkit-gradient(linear, left top, left bottom, from(#f4f2f2), color-stop(.2, white), color-stop(.8, #f4f2f2), to(white)); border-top: 1px solid white;}#theme-options-wrap #icon-tools { position: relative; top: -10px;}#theme-options-wrap input, #theme-options-wrap textarea { padding: .7em;}
With this additional CSS, the form will appear as shown in Figure 7, “The Options form with our new custom CSS”.
We can certainly take this much further, however, anything more would be beyond the scope of this tutorial. Here, we’ve just added a width, some padding, and a subtle background gradient for Mozilla and Webkit-based browsers.
Now that we’ve successfully created a working Options form, we can flesh it out and add more fields. Let’s add a new section that allows the user of the theme to upload a logo.
The first step is to add a new add_settings_field
to the register_and_build_fields
function that we created:
Example 14.
(excerpt)theme
/functions/admin-menu.php
add_settings_field('logo', 'Logo:', 'logo_setting', __FILE__, 'main_section'); // LOGO
Next, we create the logo_setting
callback function that we specified above. This handles the creation and echoing of the input:
Example 15.
(excerpt)theme
/functions/admin-menu.php
function logo_setting() { echo '<input type="file" name="logo" />';}
That should do it (almost)—it’ll add a new field to the page. Remember, the do_settings_sections
function cycles through all of the settings fields and renders them on the page. As you can see in Figure 8, “The file upload field for the logo option”, a file upload field is now displayed.
Okay, I lied! True, we’ve added the input to the page, but we haven’t written the logic that will handle the process of uploading and saving the image so that it can be accessed.
Because we’re now uploading files from our form, we need to add the enctype
attribute to the form:
Example 16.
(excerpt)theme
/functions/admin-menu.php
<form method="post" action="options.php" enctype="multipart/form-data">
This attribute determines how the form data will be encoded.
Continuing on, we need to perform a bit of validation, then upload the image to the server. If you’ll refer back to the register_setting
definition, you’ll see it offers a third parameter that can handle any specific operations or sanitizing. We called ours validate_setting
again:
Example 17.
(excerpt)theme
/functions/admin-menu.php
register_setting('plugin_options', 'plugin_options', 'validate_setting');
This is the perfect place to ensure that the user uploaded an image (and not, for example, an .exe
file), and then upload the file to the server. Change your validate_setting
function to reflect the following code:
Example 18.
(excerpt)theme
/functions/admin-menu.php
function validate_setting($plugin_options) { $keys = array_keys($_FILES); $i = 0; foreach ( $_FILES as $image ) { // if a files was upload if ($image['size']) { // if it is an image if ( preg_match('/(jpg|jpeg|png|gif)$/', $image['type']) ) { $override = array('test_form' => false); // save the file, and store an array, containing its location in $file $file = wp_handle_upload( $image, $override ); $plugin_options[$keys[$i]] = $file['url']; } else { // Not an image. $options = get_option('plugin_options'); $plugin_options[$keys[$i]] = $options[$logo]; // Die and let the user know that they made a mistake. wp_die('No image was uploaded.'); } } // Else, the user didn't upload a file. // Retain the image that's already on file. else { $options = get_option('plugin_options'); $plugin_options[$keys[$i]] = $options[$keys[$i]]; } $i++; } return $plugin_options;}
This will be the most confusing section of our code. When a file is uploaded, it’s made available via the $_FILES
superglobal variable. This array will contain information about the name, type, tmp_name
, error, and size of the file. However, in this case, we can’t assume that only one file is being uploaded at a time. In fact, your Options page could include multiple file inputs. As such, we must use a foreach
statement to filter through all of the items in the $_FILES
array. Within the foreach
statement, each uploaded image’s data will be represented via the $image
array.
We first determine if the image’s size is a size greater than 0, to ensure that the user did upload a file.
Next, we perform a modest level of validation, to make sure that the user uploaded an image and not some other sort of file. Truthfully, in any other situation, this approach wouldn’t be adequate. A user could still change the extension of a file to, for instance, .png
, and successfully upload their file. However, because this page is already limited to administrators only, this validation is meant more as a convenience for them. Should you require stronger protection for image uploads, use the getimagesize
PHP function.
This preg_match
function determines if the regular expression jpg|jpeg|png|gif
is included in the image type. If it is, we can assume that, most likely, the user did upload an image.
Next, we call the wp_handle_upload
WordPress function, which will take care of moving and saving the image to the uploads
directory of your WordPress folder.
$file
will now be equal to an array of data containing the information about the upload—most notably, the URL of the location where it was saved (accessed with $file['url']
).
Lastly, we add a new key to our plugin_options
option, and make it equal to a path to the image on the server.
That’s the basic overview of uploading images. Truthfully, this script does more than I’ve described, but, as this tutorial is specifically about creating an Options page, I don’t want to stray too far from that specific topic. We can always discuss this function more within this article’s comments if you wish.
With that out of the way, just like with the banner_heading
option, we can access our logo from our theme files by writing this code:
<?php $options = get_option('plugin_options'); ?><img src="<?php echo $options['logo']; ?>" alt="Logo" />
If you’ve followed and worked along with this entire tutorial, give yourself a pat on the back. The most confusing part of the Settings API is memorizing all of its functions; however, once you do, you then have access to a great deal of power. For instance, we only created two options in this tutorial, but now, creating a new option will take you less than a minute!
So what could be the next step, if you want to take your Options page further? Try adding a layer of JavaScript to allow for the creation of new options dynamically, without having to return to your plugin file!
Frequently Asked Questions (FAQs) about WordPress Options Panel
How Can I Create a Custom Options Page in WordPress?
Creating a custom options page in WordPress involves a few steps. First, you need to add a new function in your theme’s functions.php file. This function will use the add_menu_page() or add_submenu_page() function to create a new page in the WordPress admin area. Then, you need to create a callback function that will output the HTML for your options page. This function should include form fields for all the options you want to add. Finally, you need to register your settings using the register_setting() function, so WordPress knows to save them in the database when the options page is submitted.
What is the Purpose of the Options Page in WordPress?
The options page in WordPress is a powerful feature that allows you to add custom settings for your theme or plugin. These settings can be used to control various aspects of your theme or plugin’s functionality, such as layout, colors, text, and more. By providing an options page, you give users the ability to customize their experience and use your theme or plugin in a way that best suits their needs.
How Can I Add Fields to My Options Page?
Adding fields to your options page involves creating form elements in the callback function for your options page. These form elements can include text fields, checkboxes, radio buttons, select menus, and more. Each field should have a unique name that you can use to retrieve its value from the database. You can use the settings_fields() and do_settings_sections() functions to output the necessary hidden fields and handle security aspects.
How Can I Retrieve the Values of My Custom Options?
You can retrieve the values of your custom options using the get_option() function. This function takes the name of the option as its parameter and returns its value. You can use this function in your theme or plugin files to output the value of an option and use it in your code.
How Can I Validate and Sanitize My Custom Options?
When creating an options page, it’s important to validate and sanitize user input to ensure it’s safe and valid. You can do this by creating a validation callback function and passing it as the third parameter to the register_setting() function. This function will be called when the options page is submitted, and it should return the sanitized values.
Can I Create Multiple Options Pages?
Yes, you can create multiple options pages in WordPress. Each options page should have its own function that uses the add_menu_page() or add_submenu_page() function to create the page. You can organize your options pages under a single parent menu, or create them as top-level menus.
How Can I Add Sections to My Options Page?
You can add sections to your options page by using the add_settings_section() function. This function creates a new section on your options page where you can group related fields. Each section should have a unique ID, a title, a callback function that outputs the section’s description, and the menu slug of the options page.
Can I Use the WordPress Options API with Custom Post Types?
Yes, you can use the WordPress Options API with custom post types. You can create an options page for your custom post type and use it to add custom settings that control how the post type behaves or appears on the front end.
How Can I Add a Reset Button to My Options Page?
Adding a reset button to your options page involves adding a new form element to your options page’s callback function. This button should have a name attribute that you can check for in your validation callback function. If the reset button was clicked, your validation function should return the default values for your options instead of the submitted values.
Can I Use the WordPress Options API to Create a Theme Options Page?
Yes, you can use the WordPress Options API to create a theme options page. This page can include settings that control various aspects of your theme, such as layout, colors, typography, and more. By providing a theme options page, you give users the ability to customize the look and feel of your theme to their liking.
Jeffrey Way manages CodeCanyon, an online code marketplace, and Nettuts, a popular web development tutorial site. He also ran the biggest online marketplace for buying and selling WordPress themes--Theme Forest--for 2 years.