Creating An Options / Admin Page For Your WordPress Plugin
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
1 |
add_options_page(page_title, menu_title, access_level/capability, file, [function]); |
For Management
1 |
add_management_page(page_title, menu_title, access_level/capability, file, [function]); |
For Presentation
1 |
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 toattachedoptions
. - 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:
1 2 3 4 5 6 |
//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:
1 2 3 |
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. 😛
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:
1 2 3 4 5 6 7 |
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.
1 2 3 4 5 |
// 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.
1 2 3 4 5 6 7 8 |
// 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// 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.
1 2 |
<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.
1 2 |
<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.
1 2 3 4 5 6 |
<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:
1 |
<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. 😆 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. 😉
36 Comments
John Kolbert
Very nicely written tutorial. Great breakdown. Thanks!
Veneficus Unus
Thanks John. I love your site by the way. You have some really useful tutorials. 🙂
Oh and congrats on getting your first WP bug fixed on Trac for 2.8. 😀
Lee Blue
I FINALLY understand what the ‘file’ parameter does know. That’s was a very confusing piece of this puzzle. Thanks for clearing that up.
Veneficus Unus
No problem Lee. It confused me for quite a while until I managed to piece together what it did from various tutorials & a bit of good ol’ fashioned trial & error. 😉
Rune Jensen
Great post. I found it very useful when making the newest update for SpamTask (http://wordpress.org/extend/plugins/spamtask/), which now (thanks to this post) features a rather big settings page, with AJAX and cool spam and comment statistics. Thanks!
Veneficus Unus
No problem. Glad it helped you & your plugin looks great. 🙂
Rune Jensen
Well…
I am getting really excited about designing an incredibly user-friendly admin panel, which features a lot of functions, so if you need any modifications for SpamTask, just let me know and I’ll see if I can implement them. 😉
Miller
What file do you put the ‘att_options_page()’ in? In functions.php?
Paul Robinson
Yes, all the code goes into functions.php. Although you can also place the code in other files and then include them into functions.php to keep things neat.
medical assistant
Everywhere I go its the same kind of tutorial. I was looking for some tip that tells me who to store data returned from html form from admin page of my plugin into a table I created for my plugin instead of wordpress’s options table.
Paul Robinson
You would probably have to create a custom query. Using the WP database object you can do custom queries but I’ve never used it before so can’t help you there.
If you don’t know any MySQL you’ll probably find it difficult though.
riz
Love you my man its all i was looking for … thanks for all the help
Cheers!
Paul Robinson
Hi Riz,
No problem. Glad the tutorial helped you out. 😉
Casper Reiff
It’s lovely really! But i think you might have missed some information.
How do i get the data and append it to my plug-in main function?
Paul Robinson
Hi Casper,
I’m not sure what you mean. The options page function & the main plugin function are two completely different functions. You pass data between the two using WordPress’ options table.
Neel
Thank you, and this was a real help to me. I am a novice to WordPress and wanted to create a custom menu option on the side bar. With a few changes here and there I was able to manage to create an option bar which suited my needs.
Paul Robinson
No problem Neel, glad it was helpful. 🙂
Neel
One question Paul, currently the page link is listed under Appearance, but I would like it to be under a tab which I created in the menu bar called ‘Hotels’ , or as one among the main menu bars.
Can you please provide your suggestions on it.
Thanks.
Paul Robinson
Hi,
You would use
add_submenu_page
and use the pages filename (see the list in the tutorial) or the id you used when creating parent menu in the first parameter. That should add it to the menu.Neel
I have figured out a way how to bring the page link in the menu bar by using add_menu_page, instead of add_options_page. But it gets displayed right at the bottom.Can you please suggest how to bring it on top of the menu bar, or order the menu links. Thanks
Paul Robinson
That is defined by an integer and is the last parameter of the function
add_menu_page
. Take a look on the WordPress Codex for more info.Neel
Thanks Paul. It worked
Paul Robinson
Awesome. 🙂
Glad I was able to help.
Jarrett Gucci
Can you add the plugin options page to an area inside your theme options panel?
Paul Robinson
Hi,
You should be able to if you want to, but it would require looking through the code used to generate the Theme Options panel & extending it to add in your options. Unfortunately there is no catch-all for that & it would be different for different themes.
Dave
Do you know how I can link to a settings page?
Looking for something like:
(My plugin has two settings pages and I want to link from one page to the other).
Paul Robinson
Hi Dave,
You use the
admin_url()
function. the first parameter is the path relative to the admin area. So if you wanted to link to the page I created in this tutorial you would use:In you hyperlink. I believe that’s the most common way to do it.
Dave
That works fine, thanks very much!
Dave
Paul Robinson
Not a problem Dave.
Mexx
Thnaks, nie tutorial. But you can still safe some work with foreach loops, e.g.:
// variables for the field and option names
$opt_name = array(
‘font-color’ => ‘vcom_att_font_color’,
‘timeForSkipLinkToAppear’ => ‘vcom_att_timeForSkipLinkToAppear’,
‘showSkipLink’ => ‘vcom_att_showSkipLink’,
‘SkipLinkButtonText’ => ‘vcom_att_SkipLinkButtonText’
);
//get current values from db
foreach ($opt_name as $name => $key) {
$opt_val[$name] = get_option($name);
}
$hidden_field_name = ‘mt_submit_hidden’;
// if the user has posted information this hidden field will be set to ‘Y’
if (isset($_POST[$hidden_field_name]) && $_POST[$hidden_field_name] == ‘Y’) {
// Save the posted values in the database
foreach ($opt_name as $name => $key) {
// get posted values
$opt_val[$name] = $_POST[$key];
//update values in db
update_option($name, $opt_val[$name]);
}
// Put an settings updated message on the screen
?>
<?php
}