Create an Options Page For Your WordPress Theme

Including a Theme Options page for your theme is one of the best ways to increase ease-of-use for managing a complex theme. However, a few quick Google searches later and most people give up. Such a great inclusion for theme design appears to have such little documentation, that it appears to be one of those heavily guarded secrets which only the crème de la crème of designers hold the key to.

In this article we will be incorporating an options panel for the ‘WordPress Classic’ theme. The methods you learn will allow you to very easily integrate it into an existing theme you’re working on.

Firstly, I’d like to give heaps of credit to this post at The Undersigned. A lot of the code used in this tutorial is from their post. I’m simply building on the foundation they provided – Thanks!

What we’ll be making is a section at the top of the ‘Classic’ WordPress theme to display a welcome message. This message will be customizable from an options page in the Dashboard:

Options Preview

Normally, the options page will look a mess and unstyled. However I’m sharing with you the code I use in my projects to give your page a very user-friendly look which also fits in well with the WordPress Dashboard.

The Back-End

Start of by opening the functions.php file in the /wp-content/themes/classic/ folder. The first two lines should be:

<?php if ( function_exists('register_sidebar') )

Above this, insert the following code to get started:

<?php
$themename = "WordPress Classic";
$shortname = "wpc";
$options = array (

You can set $themename and $shortname to whatever you like. The last line starts an array for all our options to go in.

array(    "name" => "Welcome Message",
        "type" => "title"),

array(    "type" => "open"),

array(    "name" => "Title",
        "desc" => "Enter a title to display for your welcome message.",
        "id" => $shortname."_welcome_title",
        "std" => "",
        "type" => "text"),

array(    "name" => "Message",
        "desc" => "Text to display as welcome message.",
        "id" => $shortname."_welcome_message",
        "type" => "textarea"),

array(  "name" => "Disable Welcome Message?",
        "desc" => "Check this box if you would like to DISABLE the welcome message.",
        "id" => $shortname."_welcome_disable",
        "type" => "checkbox",
        "std" => "false"),

array(    "type" => "close")

);

This is where we create the options to display. We are storing each option in an array so that we can insert them into a form later in the code. This saves on a lot of duplicated code. In each array, we use the following:

name – This is the title which will be displayed for this option.

desc - A description for the option.

id – This is very important. We will be using these to retrieve the option. $shortname gets replaced with whatever you set the shortname to (in our case wpc).

std – This is the ‘default’ setting for the option. For example on checkboxes we can use true or false to determine whether the box is pre-ticked or not.

type – This defines what type of option it is. For example, text, textarea, checkbox etc.

As you can see, we start with the title option. Then ‘open’ which is used for purely presentational purposes. It is used to simply open the table for our options (yeah, we’re using tables – so be sure to repent your sins!)

We next have a textbox for the title of our Welcome Message, followed by an textarea for the message itself. We then have a checkbox for disabling the welcome message, followed by ‘Close’ which simply closes any tags created by ‘open’.

And now for the rest of the code. Most of which is a bunch of WordPress functions to tell it this is an options page, so we wont go over most of it:

function mytheme_add_admin() {

    global $themename, $shortname, $options;

    if ( $_GET['page'] == basename(__FILE__) ) {

        if ( 'save' == $_REQUEST['action'] ) {

                foreach ($options as $value) {
                    update_option( $value['id'], $_REQUEST[ $value['id'] ] ); }

                foreach ($options as $value) {
                    if( isset( $_REQUEST[ $value['id'] ] ) ) { update_option( $value['id'], $_REQUEST[ $value['id'] ]  ); } else { delete_option( $value['id'] ); } }

                header("Location: themes.php?page=functions.php&saved=true");
                die;

        } else if( 'reset' == $_REQUEST['action'] ) {

            foreach ($options as $value) {
                delete_option( $value['id'] ); }

            header("Location: themes.php?page=functions.php&reset=true");
            die;

        }
    }

    add_theme_page($themename." Options", "".$themename." Options", 'edit_themes', basename(__FILE__), 'mytheme_admin');

}

function mytheme_admin() {

    global $themename, $shortname, $options;

    if ( $_REQUEST['saved'] ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings saved.</strong></p></div>';
    if ( $_REQUEST['reset'] ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings reset.</strong></p></div>';

?>
<div class="wrap">
<h2><?php echo $themename; ?> settings</h2>

<form method="post">

<?php foreach ($options as $value) {

Next is the code which tells WordPress how to display the ‘type’ of option used (title, open, close, text, textarea, checkbox etc.)

switch ( $value['type'] ) {

case "open":
?>
<table width="100%" border="0" style="background-color:#eef5fb; padding:10px;">

<?php break;

case "close":
?>

</table><br />

<?php break;

case "title":
?>
<table width="100%" border="0" style="background-color:#dceefc; padding:5px 10px;"><tr>
    <td colspan="2"><h3 style="font-family:Georgia,'Times New Roman',Times,serif;"><?php echo $value['name']; ?></h3></td>
</tr>

<?php break;

case 'text':
?>

<tr>
    <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
    <td width="80%"><input style="width:400px;" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" value="<?php if ( get_settings( $value['id'] ) != "") { echo get_settings( $value['id'] ); } else { echo $value['std']; } ?>" /></td>
</tr>

<tr>
    <td><small><?php echo $value['desc']; ?></small></td>
</tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>

<?php
break;

case 'textarea':
?>

<tr>
    <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
    <td width="80%"><textarea name="<?php echo $value['id']; ?>" style="width:400px; height:200px;" type="<?php echo $value['type']; ?>" cols="" rows=""><?php if ( get_settings( $value['id'] ) != "") { echo get_settings( $value['id'] ); } else { echo $value['std']; } ?></textarea></td>

</tr>

<tr>
    <td><small><?php echo $value['desc']; ?></small></td>
</tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>

<?php
break;

case 'select':
?>
<tr>
    <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
    <td width="80%"><select style="width:240px;" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>"><?php foreach ($value['options'] as $option) { ?><option<?php if ( get_settings( $value['id'] ) == $option) { echo ' selected="selected"'; } elseif ($option == $value['std']) { echo ' selected="selected"'; } ?>><?php echo $option; ?></option><?php } ?></select></td>
</tr>

<tr>
    <td><small><?php echo $value['desc']; ?></small></td>
</tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>

<?php
break;

case "checkbox":
?>
    <tr>
    <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
        <td width="80%"><? if(get_settings($value['id'])){ $checked = "checked=\"checked\""; }else{ $checked = ""; } ?>
                <input type="checkbox" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" value="true" <?php echo $checked; ?> />
                </td>
    </tr>

    <tr>
        <td><small><?php echo $value['desc']; ?></small></td>
   </tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>

<?php         break;

}
}
?>

Basically, if the ‘type’ is text, we display a textbox with the title and desc tags next to it. The same goes for each of the others.

Note that we are using tables and inline-styling. Seriously, repent your sins ;)

Next is the final piece of code for the options page. It displays ‘Submit’ and ‘Reset’ buttons. At the end is the final code to tell WordPress to add this as a page in the Admin Dashboard.

<p class="submit">
<input name="save" type="submit" value="Save changes" />
<input type="hidden" name="action" value="save" />
</p>
</form>
<form method="post">
<p class="submit">
<input name="reset" type="submit" value="Reset" />
<input type="hidden" name="action" value="reset" />
</p>
</form>

<?php
}

add_action('admin_menu', 'mytheme_add_admin'); ?>

So that’s the Options page done. Test it out by enabling the Classic theme if you haven’t already, and going to Design -> WordPress Classic Options.

Making Use of the Options

Now that we’ve made the options page, we need to make them do something. For this, open header.php.

What we’ll be doing is:

  1. Retrieve the options.
  2. Check if the disable box is checked. If it hasn’t, we…
  3. Check if a title was provided. If it was, we display it.
  4. Otherwise, we display a generic “Welcome!” title.
  5. Check if a message was provided. If it was, we display it.
  6. Otherwise, a generic message is used.
  7. Finally, if the box was checked, we display nothing.

1. Retrieve Options

At the bottom of your header.php page, type the following

<?
global $options;
foreach ($options as $value) {
    if (get_settings( $value['id'] ) === FALSE) { $$value['id'] = $value['std']; } else { $$value['id'] = get_settings( $value['id'] ); }
}
?>

The above retrieves our options and places them in a variable for us to reference. The options are now avaliable as:

$wpc_welcome_disable

$wpc_welcome_title

$wpc_welcome_message

2. Check the ‘Disable’ box

<?
if ($wpc_welcome_disable == "false") { ?>

A checkbox will return “false” if unchecked, and “true” is checked. The next code we enter will only be processed if the checkbox is returning false.

3. Check a title was provided & display it

<?
if ($wpc_welcome_title) { ?>
<h4><? echo $wpc_welcome_title; ?></h4>

Here we check if there was something entered for the Title. Then display it (echo) inside H4 tags.

4. Otherwise, display a generic title

<? } else { ?>
<h4>Welcome!</h4>
<? } ?>

If there isn’t a title (else), we display a simple “Welcome” title.

5 & 6. Check a message was provided. Display it. Otherwise, generic.

<? if ($wpc_welcome_message) { ?>
<p><? echo $wpc_welcome_message; ?></p>
<? } else { ?>
<p>Hello and welcome to our site. We hope you enjoy your stay!</p>
<? } ?>

The above code uses the same methods as in the previous steps, but uses $wpc_welcome_message instead.

7. If the box was checked, display nothing

<? } else { ?>

    <!-- You could insert something here which will display when the box IS checked. -->

<? } ?>

If the box was checked, the above is processed – in our case, just a HTML comment. Ideally, you can just use the last line.

Summary

And there you have it! While the actual options we created are very simplistic, you can use the very same techniques to create a much more robust page.

For example, here is a part of the options page for my GamePress theme:

GamePress Options

Thanks for reading this tutorial and I hope it was useful. Look out for more WordPress-related articles here each week!

/* Download Complete Source Files */


74

Comments
  • Jay says:

    Anyone know how to create a dropdown menu with the categories there work with version 2.8?

  • 4 weeks: 4 wordpress themes; man this is just in time!

  • CSS designer says:

    Thanks great article

  • ibibi says:

    How can I add localization to this?

  • Karar.A.R says:

    Hi!

    This is a very good tutorial , and so helpfully.

    Just want to know is it work in 2.8 ? because I tried it in 2.7.1 and worked perfectly but in 2.8 didn’t work . So where is the error and how can I fix this to work with 2.8?

    {Sorry for my bad English}
    Thank you so much for this and may god bless you.

  • Robby says:

    Excellent! I been looking for this all day. I’ll be starting this tonight!
    I have a lot of themes that I use on many sites and this would definately speed things up for me. Thanks man!

  • Adi says:

    Just download source files and test it.
    For example if checkbox std is set to true the html checkbox is not checked.

    What can I do?

  • jon says:

    Hi, nice tutorial.

    I have just 1 question and that relates to the use of the array to store the form options in. I cant see how this avoids duplicated code as you suggest.

    Why not just write the options form as a static form rather than building it dynamically. This is not a criticism – Im new to this so am trying to learn.

    Thanks
    Jon

  • Cody says:

    Within the “switch ( $value['type'] )” block, there is a short-tag for the “checkbox” case:

    Unless your PHP is set to allow short tags, this will fail, not setting the value of the checkboxes correctly.

    Quickest fix is to add the full open tag:

  • Kai says:

    really great tutorial. many thanks

    greatings from germany

  • Lems says:

    Hey, great tutorial!

    I can make it work with a lot of types, but not a Multiple Select Box. It is either only saving 1 of the values, or only giving me one when I ask for the value. Do you have any advice for this?

    I’m using a type=”text” and comma separated list to store the values.

    Thanks!!

  • t31os says:

    Nice write-up..

    If you’re only going to store static information in variables, then you’d be better of using constants..

    You’d be able to use the constants inside a function without any need to register then in the global scope.

    So instead of…

    $var = ‘foobar’;

    function foo() {
    global $var;
    echo $var; // Output is foobar
    }

    Use a constant, for example..

    define(‘FOOBAR’,'foobar’);

    function foo() {
    echo FOOBAR; // Output is foobar
    }

    Constants are handy for data that is (as the name implies) Constant , and more so handy if they need to be referenced inside a function since they don’t require a declaration in the global scope.

    ~ t31os ~

  • Jen Duguay says:

    Thank you so much! I’m just learning Theme Options and this works like a charm (WordPress v.2.8.4)

    Maybe you can tell me if I noticed right: It looks like there is a bit of *extra/uneccessary* script for this particular Theme Options – is this true?

    === start of extra script ===


    <select style="width:240px;" name="” id=”"><option>

      

    === end ===

    I’m using your script to learn, and simply noticed this as I was looking at it through a microscope! ;)

    Thanks again, you made my day!

    Jen

  • Jen Duguay says:

    lol… okay… the code didn’t render in my comment.

    It is the section starting with === break; case ’select’: ===

    :D

  • prazetyo says:

    Very nice tutorial.
    But when I create my admin page that record categories ID, why the input can’t be save? but the other input text can be save. please someone help me.

  • Iyer says:

    hi,
    its really useful guide, i have a question , i am using textarea for input of code with ” which is now getting backslash and i tried using stripslashes but remove them but i am not able to find how to use stripslashes for removing backslashes from the code of textarea

  • GhostPool says:

    Grrr, third attempt (sorry Mods, delete other two)

    lyer find this code in functions.php (assuming you have inserted this code in there):

    echo get_settings( $value['id'] )

    And replace with:

    echo stripslashes(get_settings( $value['id'] ))

  • Sridhar Iyer says:

    thanks ghostpool [;)]

  • mihai says:

    Yes! Thanks! Worked like a charm for me. I did have to add stripslashes() to the request data though.

  • sebastien says:

    There is a big problem in this code.
    If I write “L’apostrophe”, and i submit, the résult is “L\’apostrophe”.
    If I submit one more time the result is “L\\\’apostrophe”
    and if i submit one more time the result is “L\\\\\\\’apostrophe” etc…

    It’s a big problem.
    Have you a solution please ?

    PS : very sorry for my english, i’m french :-)

  • sebastien says:

    no response ?

  • GhostPool says:

    As I said above sebastian add stripslashes to both the textarea in functions.php and the echo statement where you are calling the textarea on your website.

    Open functions.php and find:

    echo get_settings( $value['id'] )

    And replace with:

    echo stripslashes(get_settings( $value['id'] ))

    Do the same with the echo statement on your website.

  • VB says:

    I have a WP theme that has 9 widgets areas. Is it possible to make an options page that would control the widgets features, such as background color, height, width and such things?