Making a options page for a WordPress plugin isn’t actually that hard. It’s just the page WordPress have on how to do it isn’t exactly the easiest thing to read. So I thought I would show you how I made my options page for The Attached Image. Hopefully it will be easier to understand and [...]

Making a options page for a WordPress plugin isn’t actually that hard. It’s just the page WordPress have on how to do it isn’t exactly the easiest thing to read. So I thought I would show you how I made my options page for The Attached Image. Hopefully it will be easier to understand and help alot of you plugin developers out there. ;)

Decide Where You Should Put It

The first thing that you need to do is add your plugin to one of the WordPress menus. WordPress have a guide on what type of options they think should go where. Here is what they have:

Settings
Displays plugin options that only administrators should view.
Manage
Displays management controls for links, posts, categories, images, etc.
Plugins
Displays controls dealing with plugin management, not configuration options for a plugin itself.
Presentation
Displays controls for manipulation of theme/style files, sidebars, etc.
Write
Displays tools for writing content (posts and pages).
Users
Displays controls for user management.

You can also create a new top-level menu for your plugin if you require a few different option pages. I didn’t so I’m not going to explain how to do that.

Add It To That Menu

Ok, so now you’ve decided which menu you want to put it under. Now we can get started. I am assuming you already have a plugin to add the options page to. If not you can check out my past video tutorial on how to make a basic plugin or you can look out for more on making plugins in the future.

First let’s go for the easy ones. If you have decided you want to put your plugin into options, management or presentation then there are three pre-made WordPress function to make it easy.

For Options

add_options_page(page_title, menu_title, access_level/capability, file, [function]);

For Management

add_management_page(page_title, menu_title, access_level/capability, file, [function]);

For Presentation

add_theme_page(page_title, menu_title, access_level/capability, file, [function]);

Clever, huh? Now you may be thinking what’s all that gibberish inside the functions. Well I’m going to explain that now.

page_title
The text written into the pages title tag.
menu_title
The text written in the WordPress menu.
access_level/capability
The user level required to have access to the options page. Level 8 is generally good for Admin only.
file
A tricky one. The name written in the url when accessing the options page. For example, The Attached Image shows themes.php?page=attachedoptions because I set this to attachedoptions.
function
The function to call to display the options page.

Right I hope that explains those a little.

If you want to add your plugin to any of the other menus in WordPress then you can use the add_submenu_page function. It has all the same parameters as the other three functions, except for one extra at the front. That is the parent parameter. This is the name of the php file WordPress uses to access the menu you want to add to. Here is a list.

  • Write: add_submenu_page(‘post-new.php’,…)
  • Manage: add_submenu_page(‘edit.php’,…)
  • Design: add_submenu_page(‘themes.php’,…)
  • Comments: add_submenu_page(‘edit-comments.php’,…)
  • Settings: add_submenu_page(‘options-general.php’,…)
  • Plugins: add_submenu_page(‘plugins.php’,…)
  • Users: add_submenu_page(‘users.php’,…)

You can’t just call one of those functions in your plugin though, it just won’t work. You have to do it in a special way. Like this:

//First use the add_action to add onto the WordPress menu.
add_action('admin_menu', 'att_add_options');
//Make our function to call the WordPress function to add to the correct menu.
function att_add_options() {
	add_theme_page('The Attached Image Options', 'The Attached Image', 8, 'attachedoptions', 'att_options_page');
}

As you can see you define a function and hand it to the add_action function using the admin_menu hook to have it run it. It’s sometimes a little tricky to understand, but it sinks in eventually. ;)

Creating A Options Page

Remember the function given to the last parameter of add_theme_page in our example? Well we make that function and the output creates our options page. To see if all is working all you need to do is use something like this example:

function att_options_page() {
      echo 'Testing. 1, 2, 3. Testing.';
}

If you see that on your options page then your spot on course. If it isn’t working do not pass go, do not collect £200 and go back and check you’ve done everything correctly. Right, got it working? Good.

Saving Those Options

Having an options page is fine, but if you don’t know how to save the options the user picks, it will be no help at all. That’s where this part comes in. I don’t know whether there is a better way to do this, but this way is my way, I like it and it works. :P

First we assign some variables. I’ll use The Attached Image’s option page as an example, I’ll clip out some of the fields though or this tutorial will become very big, very fast. Let’s look at the first bit:

function att_options_page() {
    // variables for the field and option names
    $opt_name = array('img_size' =>'att_img_size',
			      'css_class' => 'att_css_class',
			      'img_width' => 'att_img_width',
			      'img_height' => 'att_img_height');
    $hidden_field_name = 'att_submit_hidden';

Ok, I use an array to hold both key’s (for easy reference) and the field names I am using for both the form & storage in the database. I just append a little three letter code on the front as not to conflict with any other plugins or options. The hidden field name is used later as a test for form submission.

    // Read in existing option value from database
    $opt_val = array('img_size' => get_option( $opt_name['img_size'] ),
			   'css_class' => get_option( $opt_name['css_class'] ),
			   'img_width' => get_option( $opt_name['img_width'] ),
			   'img_height' => get_option( $opt_name['img_height'] ));

Next we get the values back from the database using the get_option() function, we use the $opt_name array from before so that if any names are changed we don’t have to change a lot of different things. These values are used to re-populate the form so the user can see what options are already selected.

    // See if the user has posted us some information
    // If they did, this hidden field will be set to 'Y'
    if(isset($_POST[ $hidden_field_name ]) && $_POST[ $hidden_field_name ] == 'Y' ) {
        // Read their posted value
        $opt_val = array('img_size' => $_POST[ $opt_name['img_size'] ],
			       'css_class' => $_POST[ $opt_name['css_class'] ],
			       'img_width' => $_POST[ $opt_name['img_width'] ],
			       'img_height' => $_POST[ $opt_name['img_height'] ]);

As you can see by the comment, if the form has been submitted then the hidden form value will be set to ‘Y’ and it will be set in the POST array. If this is true, we need to re-populate the $opt_val array with the values from the POST array instead of from the database. Again we use the $opt_name array just incase names change.

        // Save the posted value in the database
        update_option( $opt_name['img_size'], $opt_val['img_size'] );
		update_option( $opt_name['css_class'], $opt_val['css_class'] );
		update_option( $opt_name['img_width'], $opt_val['img_width'] );
		update_option( $opt_name['img_height'], $opt_val['img_height'] );
		update_option( $opt_name['default_img'], $opt_val['default_img'] );
		update_option( $opt_name['href'], $opt_val['href'] );
		update_option( $opt_name['alt'], $opt_val['alt'] );
		update_option( $opt_name['link_title'], $opt_val['link_title'] );
		update_option( $opt_name['img_tag'], $opt_val['img_tag'] );
		update_option( $opt_name['echo'], $opt_val['echo'] );
		update_option( $opt_name['href_rel'], $opt_val['href_rel'] );
		update_option( $opt_name['img_order'], $opt_val['img_order'] );

        // Put an options updated message on the screen

?>
<div id="message" class="updated fade">
  <p><strong>
    <?php _e('Options saved.', 'att_trans_domain' ); ?>
    </strong></p>
</div>
<?php
	}
?>

Finally we use update_option to update the options saved in the database. If it’s the first time and the option doesn’t exist yet then the same function will create it & then update it any time after that. We then show a nice message to show the options are saved. The _e is used for translation. That curly brace is the end of the previous if not the end of the function.

Creating The Form

We have made the code for saving the options, but there isn’t a form to give any options. Let’s make that now. Again I’ll use the shortened but matching part of my plugin.

First let’s open up the standard WordPress wrapper so our text looks all neat, and matches the rest of WordPress.

<div class="wrap">
<h2><?php _e( 'The Attached Image', 'att_trans_domain' ); ?></h2>

Again the _e is for translation. Try to use it for all major headers.

<form name="att_img_options" method="post" action="<?php echo str_replace( '%7E', '~', $_SERVER['REQUEST_URI']); ?>">
  <input type="hidden" name="<?php echo $hidden_field_name; ?>" value="Y">

Here we open a typical form, the name attribute should just match your plugin name. Then we have our hidden field so we can tell if the form had been submitted. There are a lot of different type of inputs for forms on option pages, but I’ll try to cover text fields and drop down lists. First the drop down list.

 <select name="<?php echo $opt_name['img_size']; ?>">
        <option value="thumb" <?php echo ($opt_val['img_size'] == "thumb") ? 'selected="selected"' : ''; ?> >Thumbnails</option>
        <option value="medium" <?php echo ($opt_val['img_size'] == "medium") ? 'selected="selected"' : ''; ?> >Medium</option>
        <option value="large" <?php echo ($opt_val['img_size'] == "large") ? 'selected="selected"' : ''; ?> >Large</option>
        <option value="full" <?php echo ($opt_val['img_size'] == "full") ? 'selected="selected"' : ''; ?> >Full Size</option>
</select>

We use the name from the array so if posts back to the correct name. That is very important. Next we give some values, your plugin must expect these values or they will be useless. Then we have a little bit of inline php to decide which is already selected. It is a simple ternary operator. It works like an if. So if $opt_val['img_size'] is equal to “whatever” the echo selected="selected" else echo nothing. Make sense? Good.

Next is the text fields:

<input type="text" name="<?php echo $opt_name['css_class']?>" value="<?php echo $opt_val['css_class']; ?>" />

These are simple, you echo the name as before & just echo the value straight into the value attibute.

Some people have asked about radio buttons, but they are exactly like the drop down lists. Just use <input type="checkbox" name="$opt_name['img_size']" /> with that long PHP ternary in as well. You would also use the same name in each checkbox so that only one can be selected at a time.

And Relax!

That’s about it really. Just remember that using tables is probably a good idea since it’s the best way to present the information… I know shock, horror I said tables. Also if you use a table put the class form-table in it and make sure to use th tags for headers and have a tbody around the body of the table or the WordPress CSS won’t style it to match the rest of the admin.

A Little Tip

Something that is useful when making an admin. Everytime you need to do large blocks of HTML don’t echo it out, instead break out of PHP and just write HTML as normal. Also after you have finished your options page don’t forget you were working inside a function. If you have any errors such as expecting curly brace or unexpected $end then you have probably forgot to close your function.

I hope this tutorial has been of some help. I think it’s probably ended up being as complicated as the WordPress article & now I understand why that article is that complicated. :lol: At least this one shows you how to use an array to handle multiple values instead of just one. If you have anything you’d like to add or you have a problem then leave a comment & I’ll get back to you ASAP. ;)