Creating a theme option page?

I have a template page in WordPress that I want the Admin to be able to change the text on that page. I’d love to learn how to make a plugin (I know how to make a plugin so that it shows up in WP, installs when the user sets it to activate, and then create the admin panel) that shows just one text field, and the data the person enters is passed to the template page.

If I could have help finding a tutorial or simple advice on how to do this, it would be greatly appreciated.

Related posts

Leave a Reply

3 comments

  1. An example code for an options-page for a theme. Copy this code in the functions.php of the theme.

    if ( !function_exists('localizing_theme_setup') ) {
    
        function localizing_theme_setup() {
    
            localizing_constants();
    
            // Make theme available for translation
            // Translations can be filed in the /languages/ directory
            load_theme_textdomain( FB_LT_TEXTDOMAIN, TEMPLATEPATH . '/languages' );
    
            // instance class
            $localizing_theme_options = new localizing_theme_options();
        }
    
    }
    add_action( 'after_setup_theme', 'localizing_theme_setup' );
    
    function localizing_constants() {
    
        define( 'FB_LT_TEXTDOMAIN', 'localizing' );
    }
    
    if ( !class_exists( 'localizing_theme_options' ) ) {
        class localizing_theme_options {
    
            // constructor
            function localizing_theme_options() {
    
                add_action( 'admin_init', 
                    array(&$this, 'localizing_theme_options_init') 
                ); 
                add_action( 'admin_menu', 
                    array(&$this, 'localizing_theme_options_add_page') 
                );
            } 
    
            // Plugin options initialisieren 
            function localizing_theme_options_init() { 
                register_setting( 
                    'localizing_theme_options', 
                    'localizing_theme', 
                    array(&$this, 'localizing_theme_options_validate') 
                ); 
            } 
    
            // Menu page Seite hinzufuegen 
            function localizing_theme_options_add_page() { 
                add_theme_page( 
                    __( 'Set your Localizing Settings', FB_LT_TEXTDOMAIN ), 
                    __( 'Localizing Settings', FB_LT_TEXTDOMAIN ), 
                    'switch_themes', 
                    'localizing_settings', 
                    array( &$this, 'localizing_theme_options_do_page' ) 
                ); 
            } 
    
            // HTML, Simple Options Page 
            function localizing_theme_options_do_page() { 
                ?> 
                <div class="wrap"> 
                    <h2><?php _e( 'Localizing Settings', FB_LT_TEXTDOMAIN ); ?></h2> 
                    <form method="post" action="options.php"> 
    
                        <?php 
                        settings_fields('localizing_theme_options');
                        $options = get_option('localizing_theme');
                        $available_languages_files = get_available_languages();
                        if ( !empty( $available_languages_files ) ) {
                            // Translate the list into something that's easier to search
                            foreach ( $available_languages_files as $available_language ) {
                                $parts = explode( '_', $available_language );
    
                                if ( empty( $parts[0] ) )
                                    continue;
    
                                $available_languages[ strtolower( $parts[0] ) ] = $available_language;
    
                                $santized = strtolower( $available_language );
                                $santized = str_replace( '_', '-', $santized );
                                $available_languages[$santized] = $available_language;
                                $all_available_languages[] = $available_language;
                            }
                        }
                        ?>
                        <table class="form-table">
                            <tr>
                                <th scope="row"> 
                                    <?php _e( 'Available languages', FB_LT_TEXTDOMAIN ); ?> 
                                </th> 
                                <td>
                                    <input type="text" disabled="disabled" name="" 
                                    value="<?php echo implode( ', ', $all_available_languages ); ?>" />
                                    <br />
                                    <p><?php _e( 'This languages was found in the languages folder of this install.', FB_LT_TEXTDOMAIN ); ?></p>
                                </td>
                            </tr>
    
                            <tr valign="top"> 
                                <th scope="row"> 
                                    <?php _e( 'A example checkbox', FB_LT_TEXTDOMAIN ); ?> 
                                </th> 
                                <td>
                                    <input name="example_name[myoption1]" type="checkbox"  
                                    value="1" <?php checked('1', 
                                    $options['myoption1']); ?> />
                                </td> 
                            </tr> 
                            <tr valign="top"> 
                                <th scope="row">A example text</th> 
                                <td>
                                    <input type="text" name="example_name[mytext]" 
                                    value="<?php echo $options['mytext']; ?>" />
                                </td> 
                            </tr> 
                        </table> 
    
                        <p class="submit"> 
                            <input type="submit" class="button-primary" value="<?php _e( 'Save Changes', FB_LT_TEXTDOMAIN ); ?>" /> 
                        </p> 
    
                    </form> 
                </div> 
                <?php    
            } 
    
            // Sanitize und validiere input 
            // (Akzeptiert ein array, return ein sanitized array) 
            function localizing_theme_options_validate($input) { 
                // erster Wert muss 0 oder 1 sein 
                $input['option1'] = ( $input['option1'] == 1 ? 1 : 0 ); 
    
                // Wert mit text 
                $input['sometext'] =  wp_filter_nohtml_kses($input['sometext']); 
    
                return $input; 
            } 
    
        } // end class
    } // end if class exists
    

    this is my options from this code:

    alt text

    I hope you understand the code, is also an dummy, works, but is not so fine in the php-codex for classes.

  2. Here is my way:

    // get some info from the stylesheet (we need theme name & version)
    $theme = wp_get_theme();
    
    define('THE_THEME', strip_tags($theme->Name));    //  this is used as option name
    define('THEME_VERSION', trim($theme->Version));
    
    // default theme settings, the reason for a function is to avoid using a global array :)
    function default_theme_options(){
      return array(
        'version' => '1.4.5',  // we use this to sync options between different theme versions
        'my_textfield' => 'A simple text field',
        'my_checkbox' => false,
        'my_select' => 2,
        'my_texarea' => 'Just a text area bla blah',
        'my_radio' => '3rd',
        'my_multicheck' => '1,3',
      );
    }
    
    // make the theme settings are properly set up
    add_action('after_setup_theme', 'check_theme_options');
    function check_theme_options(){
    
      // get current settings
      $options = get_option(THE_THEME);
    
      // get default settings
      $defaults = default_theme_options();
    
      // make sure we have the theme options stored in the db, if not store the default ones
      if(!$options) update_option(THE_THEME, $defaults);
    
      // new theme version? synchronize options then
      if(version_compare($options['version'], THEME_VERSION, '!=')):
    
         // check for new options
         foreach($defaults as $option => $value)
           if(!array_key_exists($option, $options)) $options[$option] = $defaults[$option];
    
         // remove deprecated options if any
         foreach($options as $option => $value)
           if(!array_key_exists($option, $defaults)) unset($options[$option]);
    
         // update
         update_option(THE_THEME, $options);
      endif;
    }
    
    
    // create the menu entry and link it to the form
    add_action('admin_menu', 'add_options_menu');
    function add_options_menu(){
      add_theme_page(
        __('Theme settings'),      // page title
        'My Theme Name',           // menu title
        'edit_theme_options',      // show the theme settings to all users who have this capability
        'my_theme_options_page',   // menu slug
        'the_theme_options_form'   // the fields, function below
      );
    }
    
    
    // trigger when the form is submitted
    add_action('admin_post_save_my_options', 'save_my_options');
    function save_my_options() {
    
      // check permissions and referer
      check_admin_referer('theme-settings');
      if(!current_user_can('edit_theme_options')) wp_die(__('You are not authorised to perform this operation.'));
      $options = get_option(THE_THEME); // get the current settings
    
      // change options
      foreach (default_theme_options() as $key => $value)
        if(isset($_POST[$key]))
          if(is_array($_POST[$key])) $options[$key] = strip_tags(implode(',', $_POST[$key]));
          else $options[$key] = current_user_can('unfiltered_html') ? stripslashes((string)$_POST[$key]) : stripslashes(wp_filter_post_kses((string)($_POST[$key])));
    
      // update settings with the post data
      update_option(THE_THEME, $options);
    
      // reload options page
      wp_redirect(admin_url('admin.php?page=my_theme_options_page&updated=true'));
    }
    
    
    // the theme settings form
    function the_theme_options_form() {
      if(!current_user_can('edit_theme_options')) wp_die(__('You are not authorised to perform this operation.'));
      ?>
      <div class="wrap">
    
        <?php screen_icon('themes'); ?><h2><?php echo get_admin_page_title(); ?></h2>
    
        <form id="theme-settings-form" action="<?php echo admin_url('admin-post.php?action=save_my_options'); ?>" method="post" enctype="multipart/form-data">
    
         <?php if (isset($_GET['updated'])): // just updated? ?>
         <div class="updated fade below-h2">
           <p><?php _e('Settings saved.'); ?></p>
         </div>
         <?php endif; ?>
    
    
        <table class="form-table">
          <tr>
              <th scope="row">
                <label for="my_textfield"><?php _e("A simple textfield"); ?></label>
              </th>
              <td>
                <input id="my_textfield" size="20" name="my_textfield" type="text" value="<?php echo get_my_option('my_textfield'); ?>" />
              </td>
          </tr>
    
          <tr>
              <th scope="row">
                <label for="my_checkbox"><?php _e("Checkbox test"); ?></label>
              </th>
              <td>
                <input type="hidden" name="my_checkbox" value="0">
                <input id="my_checkbox" name="my_checkbox" type="checkbox" value="1" <?php checked('1', get_my_option('my_checkbox')) ?> />
              </td>
          </tr>
    
          <tr valign="top">
              <th scope="row">
                <label for="my_select"><?php _e("Multiple select field"); ?></label>
              </th>
              <td>
                <select name="my_select" id="my_select">
                  <option value="1" <?php selected('1', get_my_option('my_select')) ?>><?php _e("option 1"); ?></option>
                  <option value="2" <?php selected('2', get_my_option('my_select')) ?>><?php _e("option 2"); ?></option>
                  <option value="3" <?php selected('3', get_my_option('my_select')) ?>><?php _e("option 3"); ?></option>
                </select>
              </td>
          </tr>
    
          <tr valign="top">
              <th scope="row">
                <label for="my_texarea"><?php _e("A textarea"); ?></label>
              </th>
              <td>
                <textarea rows="6" cols="40" name="my_textarea" id="my_textarea" class="code"><?php echo esc_html(get_my_option('my_textarea')); ?></textarea>
              </td>
          </tr>
    
          <tr valign="top">
              <th scope="row">
                <?php _e("A radio group:"); ?>
              </th>
              <td>
               <label for="my_radio_yes">
                 <input name="my_radio" id="my_radio_yes" type="radio" value="yes" <?php checked('yes', get_my_option('my_radio')); ?> />
                  <?php _e("Yes"); ?>
               </label>
               &nbsp;&nbsp;
               <label for="my_radio_no">
                 <input name="my_radio" id="my_radio_no" type="radio" value="no" <?php checked('no', get_my_option('my_radio')); ?> />
                  <?php _e("No"); ?>
               </label>
               &nbsp;&nbsp;
               <label for="my_radio_whatever">
                 <input name="my_radio" id="my_radio_whatever" type="radio" value="whatever" <?php checked('whatever', get_my_option('my_radio')); ?> />
                  <?php _e("Whatever"); ?>
               </label>
              </td>
          </tr>
    
          <tr valign="top">
              <th scope="row">
                 <?php _e("Multiple checkbox option (eg. a list of categories):"); ?>
              </th>
              <td>
                 <?php foreach(get_terms('category') as $term): // hidden input not needed here because we only send checked options ?>
                 <label for="my_multicheck_<?php echo $term->term_id; ?>">
                   <input id="my_multicheck_<?php echo $term->term_id; ?>" name="my_multicheck[]" type="checkbox" value="<?php echo $term->term_id; ?>" <?php checked(in_array($term->term_id, explode(',', get_my_option('my_multicheck')))); ?> />
                   <?php echo $term->name; ?>
                 </label>
                 <br />
                 <?php endforeach; ?>
              </td>
          </tr>
    
          <tr valign="top">
              <th scope="row">
                 &nbsp;
              </th>
              <td>
                 <input type="submit" class="button-secondary" name="submit" value="<?php _e("Save Changes"); ?>" />
              </td>
          </tr>
    
        </table>
        <?php wp_nonce_field('theme-settings'); ?>
    
        </form>
    
      </div>
      <?php
    }
    
    
    // apis -- eg. echo get_my_option('my_textfield');
    function get_my_option($what){
      // check if it's a theme option or a normal wp option
      if($what && !array_key_exists((string)$what, default_theme_options())) return get_option($what);
    
      // it's a theme option
      $options = get_option(THE_THEME);
      return $options[$what];
    }
    
    
    function update_my_option($what, $value){
      // check if it's a theme option or a normal wp option
      if($what && !array_key_exists((string)$what, default_theme_options())) return update_option($what, $value);
    
      // it's a theme option
      $options = get_option(THE_THEME);
      $options[$what] = $value;
      return update_option(THE_THEME, $options);
    }
    

    This is just a short adaptation from the theme settings I implemented in my theme, which is much more complex than this.

    Note that hidden input with 0 value – this is a trick to force the form to send $_POST['my_checkbox'] even if the field is unchecked.

    alt text

  3. Why do you want special admin panel for this? It seems like something that can simply be handled by page with custom template if necessary.

    You can also load content of non-public page by code and use it where you need it.

    See Pages in Codex.