April 24, 2011

WordPress Settings API Tutorial Follow-Up

I received a lot of feedback on my Settings API tutorial (thank you so much!) and a few people found some bugs. There was also confusion on how to reference these options in the theme. Well, I have an updated class file and answers to your questions in this post!

Updated PHP and CSS files

Download the files (updated June 5, 2011)

In my WordPress parent theme, Bolts, I’ve been using the same code from my tutorial and making various improvements along the way. These include:

  • Options being saved properly
  • Checkboxes being set & remembered properly
  • Using checked() and selected() instead of conditional statements
  • A pre-written function to easily retrieve settings from the database

Implementing the class in your own theme

Put the class in your theme folder, then put this code in your functions.php file:

if ( file_exists( STYLESHEETPATH . '/class.my-theme-options.php' ) )
	include_once( STYLESHEETPATH . '/class.my-theme-options.php' );

Of course, if you’re changing the name of the class and the filename, apply those changes to this code.

The style of the theme options page now matches the tabbed style in WordPress 3.1. Download and tweak to your heart’s desire.

Getting options from the database

Put this in your functions.php file:

function mytheme_option( $option ) {
	$options = get_option( 'mytheme_options' );
	if ( isset( $options[$option] ) )
		return $options[$option];
	else
		return false;
}

Now you can use the mytheme_option() function to reference any saved option you want. Just put the option ID in the parentheses (the ‘id’ field specified when creating an option in the theme options class). For example: mytheme_option( 'rss_url' ) would return http://example.com/feed/ (or whatever was specified on the theme options page). For checkboxes, just use a conditional statement:

if ( mytheme_option( 'footer_credit_link' ) )
	echo '<p>Powered by <a href="http://example.com/">Example.com</a> and <a href="http://wordpress.org/">WordPress</a><p>';

Thanks to everyone again for using my theme options class and leaving comments to help me improve it! In the future, you’ll be able to find the most recent version of my theme options class in the Bolts theme, which will be in its first stable release next week! (Also, if I can manage it, it will be available in the WordPress theme repository!)You can download Bolts on Github, but it is not currently being maintained.

View this post online: http://alisothegeek.com/2011/04/wordpress-settings-api-tutorial-follow-up/

Leave a Reply

34 thoughts on “WordPress Settings API Tutorial Follow-Up

  1. miramez says:

    reset button is not working for me…

    • Alison Barrett says:

      Hi Miramez,

      I’m still finishing Bolts (it’s currently in Beta) and not everything works yet—unfortunately the Reset in the theme options is one of those things. Thanks for letting me know!

  2. Tim says:

    Hi again,

    Thanks for the updated code, my values are being saved.

    Now I’m having a tough time including the admin-options.css.

    I added this to the construct:
    add_action( 'admin_head', array( &$this, 'admin_css' ) );

    And added this to the class:

    public function admin_css() {
    if ( isset( $_GET['page'] ) && $_GET['page'] == 'Bolts_Theme_Options' )
    echo '' . "\n";
    }

    After adding the above, I did check the source code to see if the reference to the style sheet was there and it was not.

    Where am I going wrong??

    And thanks for all the work you’re putting into this…you’ve saved me a ton of time!!

    • Tim says:

      There was some code stripped from my comment above. Second code block, third line, between the single quotes.

      That piece of code appears exactly like the code you provided in your Settings API tutorial part 2.

      Hope that makes sense

    • Alison Barrett says:

      Try using $_GET['bolts-options'] instead of $_GET['Bolts_Theme_Options']. Basically use whatever value is in the URL when you’re on your options page.

  3. Alex says:

    The input attributes are not escaped. If you put any value with “quotes” in a text input field, it will not save the data. Use esc_attr() to clean the output first.

    Use for input and option tags…

    Input text fields:
    echo '';

    Select option tags:
    echo '' . $label . '';

    Also, consider using wp_htmledit_pre() for the textareas:
    echo '' . wp_htmledit_pre($options[$id]) . '';

  4. It says “Notice: Use of undefined constant BOLTS_TEXT_DOMAIN – assumed ‘BOLTS_TEXT_DOMAIN’ in D:\wamp\www\concepts\nano\library\extensions\functions\bolt.php on line 25″ all over the screen when PHP debug is on.

    • Alison Barrett says:

      That’s because I’m defining BOLTS_TEXT_DOMAIN in the Bolts theme. I’ll re-post the theme options code here in the next couple of days with the constant removed. Thanks!

  5. Daniel ★ says:

    Hello,

    How do I use if else type starement?

  6. Alexander Sebastian Marketing says:

    Is there a istake in this code or is it me? i am a bit new to this….

    function mytheme_option( $option ) {
    $options = get_option( ‘mytheme_options’ );

    should the function be called mytheme_options so it matches the ( ‘mytheme_options’ ); just under it?Thanks

    • ‘mytheme_options’ is what all the data is stored as in the WP database. ‘mytheme_option’ is just a custom function name to make retrieving a specific option more convenient.

  7. Alexander Sebastian Marketing says:

    Just want to say thanks for such a great tutorial! This is my first time using the settings api and this is by far the best tut i have found on it!

    Regardless i am still struggling, i hope you dont mind me asking a few questions:

    I am using thesis wordpress theme so i am using custom functions.php

    1: When i add the code at the top of the page( the second code) into my custom functions.php i get a white blank page.. im not sure why, if i change the function to “mytheme_options” from “mytheme_option” it seems to work, well my website doesnt crash at least…  is the code at the top definately right or am i making a mistake? It is definately this code that is making it crash but i cant work out why?

    2: I notice that you havnt added the id code into this section:
    $this->settings['example_text'] = array(
                ‘title’   => __( ‘Example Text Input’ ),
                ‘desc’    => __( ‘This is a description for the text input.’ ),
                ‘std’     => ‘Default value’,
                ‘type’    => ‘text’,
                ‘section’ => ‘general’
            );

    should i add this manully like

                ‘id’ => ‘mytextarea1′

    How would i add this into a field in my functions.php file, This is the section i want to add the above text area into:

    function top_bar() {
    ?>   
       
       
       
       
        <?php }
    add_action('thesis_hook_before_html','top_bar');

    Any advice would be greatly appreciated! sorry for a Newbie questions but i have been struggling with the settings api for so long..

    Thanks again
    Alex

    • 1. The function name might be conflicting with an existing function. You can change that function name to anything you want.

      2. The id is now in the square brakets part of that block of code: ['example_text'] so you don’t need to add it manually.

      If you use that first function (from your question #1) you can retrieve options from the database that way. Example:

      echo mytheme_option( 'mytextarea1' );

  8. Alexander Sebastian Marketing says:

    Hey Alison< I have run into another problem, although it may be pretty simple for you!

    I have been playing around with trying to get a simple enable/disable check box to work properly in my theme, could you please give and example of how to do this?

    i know how to add the first bit im just not sure what to add after the content i want enabled, to shoe the area that i want to disable/enable.. i hope that makes sense!

    Any help would be appreciated!

    Alex

  9. DennisSmolek says:

    How do I create the ability to ADD options. For example a set of 3 options in a section that would get called like [function1]. Then a method to ADD a section so I could have [function2],[function3], etc.
    I could do this with custom arrays and the options API by dynamically naming options but the settings API seems a bit more strict. Like I have to register all options hard coded.
    I’m still thinking it through but pulling a setting like “num_of_sections” and some sort of loop is in my head..

  10. Lee says:

    Love the tutorial it is very useful. I was wondering how to add the ability to upload an image for the logo for example?

  11. Anonymous says:

    How to display the default value if it is not set by the user?

  12. Nalio22moscow says:

    I am having trouble implementing a multicheckbox system in the options could you or anyone help please!!!

  13. lawrenced says:

    Hey you clever people..

    I’ve renamed mytheme_option to mytheme_options as the former was “already defined” and I didnt know what that meant.
    I was wondering if this is the right way to impliment the select choices options on the main theme index page (I am a beginner) ” if (mytheme_options( ‘example_select’ ) ==’choice1′) {?>no one worksno two works no three works <?php } "

  14. Jacorre says:

    I’m going to try this tutorial out thank you!

    One question I have is with select drop downs. I’d like to pull posts from a specific category or parent page and present the user with the option to select from the drop down list. Is that possible with this format?

    For example, have a Featured Post option with a select drop down of posts from a specific category? Selecting a post from the drop down will then display that post information on the homepage.

  15. Mmbee888 says:

    Do you know how to create & save dynamic fields with the setting API? I want the users to be able to add fields dynamically but having trouble saving the data with setting API.

  16. Anonymous says:

    Great article. Very clear and easy to understand. Thanks.
    It is hard to find good information on the WordPress Settings API

  17. Anonymous says:

    Thank you again Aliso for the options class you generously provided months ago. I’ve recently revised it further for my TYPO3 Importer for WordPress. Some of the changes include fuller validation with error reporting, localization, options updating and denoting fields as required.

    Of note, I sanitized my code a little below to try and prevent confusion about naming and relation to the original options class. Link to full code provided at bottom.

    Easy stuff first, options updating. I found myself wanting to update values outside of the class and this is a quick way to do so.
    [code]
    function update_my_options( $option, $value = null ) {
    $options = get_option( 'my_options' );

    if ( ! is_array( $options ) ) {
    $options = array();
    }

    $options[$option] = $value;
    update_option( 'my_options', $options );
    }
    [/code]

    Another mostly easy one, but takes more effort is localization. In the __construct() method, add the following line.
    [code]
    load_plugin_textdomain( 'my-plugin-name', false, '/my-plugin-name/languages/' );
    [/code]

    Then refer to http://codex.wordpress.org/I18n_for_WordPress_Developers#I18n_for_theme_and_plugin_developers for adding text domains and creating the POT files in the languages directory.

    I was needing to ensure that certain settings were set, validated, do some action or pass error messages along. The place I’ve learned to do so, is in the validate_settings() method.

    First, ensure integer value items are integers.
    [code]
    if ( '' != $input['import_limit'] ) {
    $input['import_limit'] = intval( $input['import_limit'] );
    }
    [/code]

    Second, make sure an option is given and is valid. In my case, is the originating TYPO3 website URL given and is that URL a TYPO3 website. Within, this code, we use the add_settings_error() function to send errors back to the user on submit. add_settings_error() is a flash message which replaces the “Settings saved” text.
    [code]
    if ( '' == $input['typo3_url'] ) {
    add_settings_error( 'typo3-options', 'typo3_url', __('Website URL is required', 'typo3-plugin-name') );
    } else {
    $typo3_url = $input['typo3_url'];
    // append / if needed and save to options
    $typo3_url = preg_replace('#(/{0,})?$#', '/', $typo3_url);
    // silly // fix, above regex no matter what doesn't seem to work on
    // this
    $typo3_url = preg_replace('#//$#', '/', $typo3_url);
    // Store details for later
    $input['typo3_url'] = $typo3_url;

    // check for typo3_url validity & reachability
    if ( ! $this->_is_typo3_website( $typo3_url ) ) {
    add_settings_error( 'typo3-options', 'typo3_url', __( "TYPO3 site not found at given Website URL", 'typo3-plugin-name' ) );
    }
    }
    [/code]

    I couldn’t ever really makes heads or tails of the API guidelines text regarding the parameters for add_settings_error() at http://codex.wordpress.org/Function_Reference/add_settings_error. So I figured on my own standard of add_settings_error( plugin-name, input-field-name, __(message text), ‘error’ or ‘updated’).

    Lastly, in case of a bad import or wanting to clear out certain parts of recently imported TYPO3 news, I put my delete actions in validate_settings().
    [code]
    if ( isset( $input['delete'] ) && $input['delete'] ) {
    switch ( $input['delete'] ) {
    case 'imports' :
    $this->delete_import();
    break;

    case 'comments' :
    $this->delete_comments();
    break;

    case 'attachments' :
    $this->delete_attachments();
    break;
    }

    unset( $input['delete'] );
    return $input;
    }
    [/code]

    Notice that in above, I unset the delete input or else, the setting would actually be saved.

    In get_settings(), delete is a radio fieldset.
    [code]
    $this->settings['delete'] = array(
    'section' => 'reset',
    'title' => __( 'Delete...', 'my-plugin-name'),
    'type' => 'radio',
    'std' => '',
    'choices' => array(
    'imports' => __( 'Prior imports', 'my-plugin-name') . ': ' . $desc_imports,
    'comments' => __( 'Imported comments', 'my-plugin-name') . ': ' . $desc_comments,
    'attachments' => __( 'Unattached media', 'my-plugin-name') . ': ' . $desc_attachments
    )
    );
    [/code]

    Lastly, since I’m modifying values in validate_settings(), I return input, instead of false at method close.
    [code]
    return $input;
    [/code]

    The TYPO3 Importer is in SVN at WordPress. You can review the code at http://plugins.svn.wordpress.org/typo3-importer/trunk/. In particular, the options class is http://plugins.svn.wordpress.org/typo3-importer/trunk/class.options.php.

  18. Anonymous says:

    The TYPO3 Importer plugin is at http://wordpress.org/extend/plugins/typo3-importer/.

  19. Dave says:

    Out of interest what was the problem causing options not to save properly? I have a similar issue where when the form is submitted it reloads all the default values, still scratching my head trying to work out where I have gone wrong..

  20. If anyone is still following this enough to help, I’d appreciate it. I’m trying to use the “select” element to display a drop down menu of pages.

    Any help would be apprecaited.

I'm speaking at WordCamp Minneapolis 2013