A complete, versatile options page class for any WordPress plugin

Building an options page for a plugin can be a daunting prospect – you want to build it in a way that works for your plugin, but also so that it works well within the WordPress UI. Many plugin authors get this painfully wrong and build incredibly unfriendly options pages that look terrible and really don’t fit into the WordPress dashboard design at all.

After putting loads of work into refactoring Seriously Simple Podcasting for the v2.0 release, I’ve developed a single class that will help you to create a versatile and user-friendly options page for your plugin that fits neatly into the WordPress dashboard. All you need to do is add this class to your plugin and modify the array of settings to handle the data that your plugin needs.

This isn’t a tutorial post, so I’m not going to walk you through this step by step, but if you use the class below you can create a WordPress options page with every type of field possible with almost no effort on your part. The field types that this class can create are:

  • Text field
  • Password field
  • Secret text field (where the saved data is not displayed on the page)
  • Text area
  • Single checkbox
  • Multiple checkboxes
  • Select box
  • Multiple select box
  • Radio buttons
  • Number field
  • Colour picker (using WordPress’ built-in colour picker script)
  • Image upload (that saves the image to your site’s media library)

I have included demo fields in the class so you can see how each field type works and what parameters you need to define for each field type – all you need to do is delete these fields and create your own.

The class uses all the WordPress Settings API functions, so it does things in the “correct” way. It also includes a mini-navigation that uses Javascript to show & hide the relevant sections.

You will find the class, along with its associated Javascript file below, but if you want to see it all in action in the context of a full plugin you can check out my WordPress Plugin Template that includes this same code. For a quick overview of what the resulting options page will look like, here’s a handy screenshot (click to enlarge):

Options page
The options page that is generated by this class

Here is the class in its entirety along with the relevant Javascript and include code:

Once you have added all this code you will find the new options page in the dashboard menu by going to Settings > Plugin Settings.

The options that are saved from this page use the $settings_base variable in the class (in this case, ‘wpt_‘)followed by the id field of each setting for their name. So the option name for the first field would be ‘wpt_text_field‘, which you can fetch using get_option( 'wpt_text_field' );.

If you can think of any other field types that you think should be included in this class then let me know in the comments.

26 thoughts on “A complete, versatile options page class for any WordPress plugin

  1. Great work, just came in handy for my very first plugin. I learned a lot about WP from friendly people like you who are willing to share their knowledge. As for your question about enhancements: how about having some sort of repeater? This would give us the ability for having “sets of settings”. Example: a playlist for an mp3 player, where each entry could for example have a title, a cover picture, etc.

    Another thought: how about storing all settings in an array into the db, instead of having multiple db calls?

    Grettings from germany


    1. In addition to the above: just found your fantastic wordpress plugin template on Github and came up with another idea on this: why not separate the field output logic? So we could use the different field types for the custom post type metaboxes as well.


      1. Thanks for the great feedback Andre! I’ll look into the idea of a ‘set’ of settings like you mention – might be a nice little enhancement. As for storing the options in a single array instead of multiple DB calls, I chose not to do that because when you are calling the options on the frontend it’s not always beneficial to call every single option when all you need is a single option. I’m not sure of the numbers with regards to performance, but I generally favour multiple options instead of one global array.

        I really like the idea of separating out the field logic so it’s usable for custom post types as well – I’ll look into enhancing the template to handle that as I think it would be a very valuable upgrade :)


      2. Glad you like my ideas. I think your template is a valuable foundation for every plugin coder, especially for beginners like me. I definitive stick with this post and will refractor my mp3 player plugin with your template as a base, especially after your next update ;-)

        For the database calls: I just was a bit concerned about the amount of database calls for each plugin. Since I love the progress in my WP coding skills, i am quite sure that there will be a lot more plugin stuff from me in the future. Right now I am working on a versatile solution to play mp3 files in a WP site, comes with different flavors like single player, footer player ith playlist, etc. Complete with custom post type. I am damn proud about my first plugin. At the moment I am struggling with a single bit: I somehow need to hook into the file upload process. First for ensuring that there are only mp3 files ready, second because I want to create preview files of the uploaded mp3 files. I have a fantastic class for hat in my arsenal, that I have allready used for another project.

        Thanks for your effort, can’t wait to see the progress in your template. Keep me informed please ;-)


  2. Hi. Thanks for this. I have a question about multi-select options.

    I need to generate the options dynamically according to the given site’s user roles. So:

    ‘id’ => ‘multi_select_box’,
    ‘label’ => __( ‘A Multi-Select Box’, ‘plugin_textdomain’ ),
    ‘description’ => __( ‘A standard multi-select box – the saved data is stored as an array.’, ‘plugin_textdomain’ ),
    ‘type’ => ‘select_multi’,
    ‘options’ => array( ‘linux’ => ‘Linux’, ‘mac’ => ‘Mac’, ‘windows’ => ‘Windows’ ),
    ‘default’ => array( ‘linux’ )

    … the options array would need to be built from another foreach and stored in a variable I guess. Here’s the foreach to generate the user roles:

    global $wp_roles;
    $all_roles = $wp_roles->roles;
    $editable_roles = apply_filters(‘editable_roles’, $all_roles);
    foreach($editable_roles as $role=>$theroles){
    echo ”.$wp_roles->role_names[$role].”;

    How could I do this and plug it into the options array? Thanks for your time.


    1. Hi Thom,

      All you need to do is save the array of user roles as a variable in this format array( 'role' => 'Role Name' ). If you’re not sure how to do that then Google should be able to help you out :)


  3. Hi,
    Thanks for this great plugin template. I am starting my first plugin with your template. I have a question though. What the “validation callback for field” is doing? Can you explain it for me?

    public function register_settings () {
    if( is_array( $this->settings ) ) {
    foreach( $this->settings as $section => $data ) {

    // Add section to page
    add_settings_section( $section, $data[‘title’], array( $this, ‘settings_section’ ), ‘html_data_table_settings’ );

    foreach( $data[‘fields’] as $field ) {

    // Validation callback for field
    $validation = ”;
    if( isset( $field[‘callback’] ) ) {
    $validation = $field[‘callback’];

    // Register field
    $option_name = $this->base . $field[‘id’];
    register_setting( ‘html_data_table_settings’, $option_name, $validation );

    // Add field to page
    add_settings_field( $field[‘id’], $field[‘label’], array( $this, ‘display_field’ ), ‘html_data_table_settings’, $section, array( ‘field’ => $field ) );


    1. The validation callback is a way of validating the submitted form data before saving it. You can create a function that checks the content of the submitted field and performs any action you like on that content before saving it to the database. A good example of this would be if you are asking people to save a URL in one of the fields – using the validation callback you can run the esc_url() function on the submitted text to make sure that it is saved as a properly formatted URL.


  4. Hey, nice job, this is fantastic!
    Im new in this whole backend hardcore programming, and I have a problem with your template. When I click “upload an Image” it just doesnt add it, if I choose a file in my pc it sends an error, and if I choose the “Use one in wordpress” or something like that option, it keeps “buffering” forever. I dont know if there is an issue with your code, i dont know perhaps some function got deprecated, or if I made a mistake. But I followed every step, and the other things are working wonderfully, hope you read this and know how to solve it.

    And of course, Thank you for sharing this, this is amazin!



  5. When I call for option value in plugin file using get_option(‘id’); this is not work means value does not show. please help how can i get option value right way. Thank you!


  6. Thanks Hugh, it saved time.
    JS code was giving me error when I tried to upload an attachment. Adding a “var” before attachment variable fixed it.

    In case we have plenty of options to offer, we should save them as an array. Do you have any idea how can I change your code to save all options in a single array i.e. one entry in wp_options table with serialized data?


  7. Hi,

    I am more of a front-end developer with some php-knowledge. I know how to normally register a custom post type, but with your plugin and your explanation I’m a bit lost where and how to register the custom post types.

    In the ‘lib’-folder I see cpt and taxomomy files, but I think I shouldn’t modify these files as the contain all sorts of variables?

    I would like to register multiple cpt’s, and the ability to switch them ‘on’ or ‘off’ using checkboxes in the settings page. How can I do this?

    Your plugin would be a huge time-saver when it comes to developing client-websites and being flexible with custom post types.

    Thanks in advance!


  8. Sir,I have used your plugin class in one of my plugin.When I active that plugin it’s gives the following error message

    ” The plugin generated 3 characters of unexpected output during activation. If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin. ”

    Please give solution!


  9. Hello,

    I know this was an old post, but I thought I’d ask if you had any suggestions for multiple image upload fields. In other words, it is returning the same value no matter which image uploader I use, on the first field, and cannot distinguish the difference in fields. I have gotten around this in the past by using class rather than id, but it doesn’t seem to work here.

    Thanks in advance, if you’re still listening.


  10. Nice Work! Im trying to understand how use the template :/ have you some kind of simple plugin where can i see how you use it? for example im trying to add some code in public function install () but cant get it working, at least if have some plugin already made with this template i can understand how it works!


  11. Good Job. :)

    It would be a great enhancemet, if there’s a repeating field aswell – or repeating fieldset. So the Admins can create multiple sets of fields.


  12. LOVE IT!
    how would you change it to save options as an array? Thats easier when turning off the plugin. i want to offer removing the options information from the database ;) – ideas? (p.s: thanks a lot – i really love it – gr8 job).


    1. i think there are some errors… in this line “if( isset( $field[‘default’] ) ) {” you are basiclly blocking assigment of data=option if no default was set which means that later on, radio and select wont show selected options.


Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s