Create WordPress Theme Options Page

Create WordPress Theme Options Page

How to Create WordPress Theme Options Page
If you design WordPress themes, you might have wanted to allow users to your customize themes or add certain functionality not pre-built in the WordPress platform. Most good WordPress themes have a Theme Options page that allows you to easily make changes to the theme and also add certain elements such as Twitter links or tweets. Creating an options page for your WordPress theme isn’t very hard. Here’s how you can add one. To keep our theme clean and organized, we will create a separate “functions” folder and create a file called theme-options.php in it. Copy-paste the following in the file. We are just defining three PHP variables.

Important: There is some problem with the way WordPress/plugin shows code. All backslashes in the code are not shown. Please make sure that the quote within quotes have a backslash just before them.

$checked = "checked=\"checked\"";

Please download any of my free WordPress themes and look at the theme options file to ensure that any errors in prasing the code on this website does not create unnecessary hurdles for you.

<?php

// Theme Options
// by Specky Geek (http://www.speckygeek.com)

$themename = "P2H";
$shortname = "p2h";
$version = "1.0";

?>

Now, we are going to define various theme options in an array. The $options variable stores various options for the theme.

<?php

// Theme Options
// by Specky Geek (http://www.speckygeek.com)

$themename = "P2H";
$shortname = "p2h";
$version = "1.0";

// Create theme options
global $options;
$options = array (

array( "name" => "General",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "Colour Scheme",
 "desc" => "Select a colour scheme for the theme.",
 "id" => $shortname."_alt_stylesheet",
 "type" => "select",
 "options" => $alt_stylesheets,
 "std" => "default.css"),

array( "name" => "Custom Feed URL",
 "desc" => "You can use your own feed URL (<strong>with http://</strong>). Paste your Feedburner URL here to let readers see it in your website.",
 "id" => $shortname."_feedurl",
 "type" => "text",
 "std" => get_bloginfo('rss2_url')),

array( "name" => "Delete Extra Feeds",
 "desc" => "WordPress adds feeds for categories, tags, etc., by default. Check this box to remove them and reduce the clutter.",
 "id" => $shortname."_cleanfeedurls",
 "type" => "checkbox",
 "std" => ""),

array( "name" => "Twitter ID'",
 "desc" => "Your Twitter user name, please. It will be shown in the navigation bar. Leaving it blank will keep the Twitter icon supressed.",
 "id" => $shortname."_twitterid",
 "type" => "text",
 "std" => ""),

array( "name" => "Facebook Page",
 "desc" => "Link to your Facebook page, <strong>with http://</strong>. It will be shown in the navigation bar. Leaving it blank will keep the Facebook icon suppressed.",
 "id" => $shortname."_facebookid",
 "type" => "text",
 "std" => ""),

array( "type" => "close"),

array( "name" => "Footer",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "Footer Text",
 "desc" => "Paste your text, copyright statements, etc., here.",
 "id" => $shortname."_footer_text",
 "type" => "textarea",
 "std" => ""),

array( "name" => "Analytics/Tracking Code",
 "desc" => "You can paste your Google Analytics or other website tracking code in this box. This will be automatically added to the footer.",
 "id" => $shortname."_analytics_code",
 "type" => "textarea",
 "std" => ""),

array( "type" => "close"),

array( "name" => "Advertisement Code",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "Adsense Code",
 "desc" => "Enter your Adsense code (or other ad network code) here.",
 "id" => $shortname."_adcode",
 "std" => "",
 "type" => "textarea"),

array( "type" => "close"),

);

?>

The $options variable is composed of a number of variables, each with a  “type”  key to determine how the element has to be handled. The options have been organized in separate “sections” the “open” and “close” markers.

Each option can have the following options:

  • name: The name of the input field.
  • desc: A short description.
  • id: The unique id of the field, prefixed by the shortname. It will be used to store as well as access the options.
  • type: The input type—select, text or textarea.
  • options: Used to declare an array of options for a select type input.
  • std: The default input value, used if no other input is given.

Now, we need to have some way for updating and saving these options. Using function p2h_add_admin() , we will add a separate menu page for theme options in WordPress administration.

function p2h_add_admin() {

 global $themename, $shortname, $options;

 if ( isset ( $_GET['page'] ) && ( $_GET['page'] == basename(__FILE__) ) ) {

 if ( isset ($_REQUEST['action']) && ( 'save' == $_REQUEST['action'] ) ){

 foreach ( $options as $value ) {
 if ( array_key_exists('id', $value) ) {
 if ( isset( $_REQUEST[ $value['id'] ] ) ) {
 update_option( $value['id'], $_REQUEST[ $value['id'] ]  );
 }
 else {
 delete_option( $value['id'] );
 }
 }
 }
 header("Location: admin.php?page=".basename(__FILE__)."&saved=true");
 }
 else if ( isset ($_REQUEST['action']) && ( 'reset' == $_REQUEST['action'] ) ) {
 foreach ($options as $value) {
 if ( array_key_exists('id', $value) ) {
 delete_option( $value['id'] );
 }
 }
 header("Location: admin.php?page=".basename(__FILE__)."&reset=true");
 }
 }

add_menu_page($themename, $themename, 'administrator', basename(__FILE__), 'p2h_admin');
add_submenu_page(basename(__FILE__), $themename . ' Options', 'Theme Options', 'administrator',  basename(__FILE__),'p2h_admin'); // Default
}

The add_menu_page() function is set to execute a function called p2h_admin, but it doesn’t exist yet. So, we will add p2h_admin() which will render the theme options form in the menu page and also execute the save and reset button triggers. If the options have been saved, it writes a message indicating so. Likewise for resets.

For rendering the options setting form, all options are evaluated using foreach loop. The switch-case method is used to render the right component.

function p2h_admin() {

    global $themename, $shortname, $version, $options;
	$i=0;

	if ( isset ($_REQUEST['saved']) && ($_REQUEST['saved'] ) )echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings saved.</strong></p></div>';
	if ( isset ($_REQUEST['reset']) && ($_REQUEST['reset'] ) ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings reset.</strong></p></div>';

?>

<div class="wrap ">
<div class="options_wrap">
<h2 class="settings-title"><?php echo $themename; ?> Settings</h2>
<form method="post">

<?php foreach ($options as $value) {
switch ( $value['type'] ) {
case "section":
?>
	<div class="section_wrap">
	<h3 class="section_title"><?php echo $value['name']; ?></h3>
 	<div class="section_body">

<?php
break;
case 'text':
?>

	<div class="options_input options_text">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		<input name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" value="<?php if ( get_option( $value['id'] ) != "") { echo stripslashes(get_option( $value['id'])  ); } else { echo $value['std']; } ?>" />
	</div>

<?php
break;
case 'textarea':
?>
	<div class="options_input options_textarea">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		<textarea name="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" cols="" rows=""><?php if ( get_option( $value['id'] ) != "") { echo stripslashes(get_option( $value['id']) ); } else { echo $value['std']; } ?></textarea>
	</div>

<?php
break;
case 'select':
?>
	<div class="options_input options_select">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		<select name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>">
		<?php foreach ($value['options'] as $option) { ?>
				<option <?php if (get_option( $value['id'] ) == $option) { echo 'selected="selected"'; } ?>><?php echo $option; ?></option><?php } ?>
		</select>
	</div>

<?php
break;
case "radio":
?>
	<div class="options_input options_select">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		  <?php foreach ($value['options'] as $key=>$option) {
			$radio_setting = get_option($value['id']);
			if($radio_setting != ''){
				if ($key == get_option($value['id']) ) {
					$checked = "checked="checked"";
					} else {
						$checked = "";
					}
			}else{
				if($key == $value['std']){
					$checked = "checked="checked"";
				}else{
					$checked = "";
				}
			}?>
			<input type="radio" name="<?php echo $value['id']; ?>" value="<?php echo $key; ?>" <?php echo $checked; ?> /><?php echo $option; ?><br />
			<?php } ?>
	</div>

<?php
break;
case "checkbox":
?>
	<div class="options_input options_checkbox">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<?php if(get_option($value['id'])){ $checked = "checked="checked""; }else{ $checked = "";} ?>
		<input type="checkbox" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" value="true" <?php echo $checked; ?> />
		<label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label>
	 </div>

<?php
break;
case "close":
$i++;
?>
<span class="submit"><input name="save<?php echo $i; ?>" type="submit" value="Save Changes" /></span>
</div><!--#section_body-->
</div><!--#section_wrap-->

<?php break;
}
}
?>

<input type="hidden" name="action" value="save" />
<span class="submit">
<input name="save" type="submit" value="Save All Changes" />
</span>
</form>

<form method="post">
<span class="submit">
<input name="reset" type="submit" value="Reset All Options" />
<input type="hidden" name="action" value="reset" />
</span>
</form>
<br/>
</div><!--#options-wrap-->

</div> <!--#wrap-->
<?php
}
add_action('admin_init', 'p2h_add_init');
add_action('admin_menu' , 'p2h_add_admin');
?>

If there’s a “section” type option, a new <div class="section_wrap"> tag is added. After this the name of the section is added within h3 tags and then <div class="section_body"> is added.

If there is an “open” type option—nothing is done. If there is a “close” type option, a “Save Changes” button is added, followed by closing tags for section_body and section_wrap divs. To have a unique button id, a counter variable $i is declared. It keeps track of section number and creates unique button id by adding to to the name.

Input types are also handled appropriately. For each of the types “text” (input type=”text”), “select” (dropdowns), “checkbox” and “textarea”, the corresponding input is displayed.

At the end of this function, add_action tag has been used to add the admin menu. Just above that you can see admin_init(). This function add (enqueues) the style and javascript files to be used by theme options page. The function p2h_add_init() does not exist yet. We will add the following code above p2h_admin() function.

function p2h_add_init() {

$file_dir=get_bloginfo('template_directory');
wp_enqueue_style("p2hCss", $file_dir."/functions/theme-options.css", false, "1.0", "all");
wp_enqueue_script("p2hScript", $file_dir."/functions/theme-options.js", false, "1.0");

}

The above function merely adds the required stylesheet and javascript files. But the files being called by this function don’t exist yet. Create a CSS stylesheet called theme-options.css and a javascript file called theme-options.js, and save them in the “function” folder. The CSS file will contain the syles for our options page. Paste the following in the theme-options.css.

.wrap{
width:98%;
}

.options_wrap h2{
font-style:normal;
font-size:28px;
margin-bottom:20px;
}
.options_wrap{
 width:750px;
 float:left;
 line-height:1.5em;
 height:auto;
}

.section_wrap{
 margin-bottom:35px;
 float:left;
 width:750px;
}

.section_body{
 border:1px solid #ddd;
 border-top:0;
 background:#f9f9f9;
 width:748px;
 float:left;
-moz-border-radius:0 0 6px 6px;

}

h3.section_title{
-moz-border-radius:6px 6px 6px 6px;
background:#F1F1F1;
border:1px solid #DDD;
color:#4E4C41;
cursor:pointer;
font-size:1.2em;
margin:0;
padding:15px 15px 15px 40px;
clear:both;
}

h3.section_title:hover{
background-color:#F2f2f2;
border:1px solid #CFCFCF;
}

h3.open {
-moz-border-radius:6px 6px 0 0;
}

h3.section_title span{
color:#AAAAAA;
float:right;
font-size:0.9em;
font-weight:normal;
}

.options_input {
 margin:35px 20px;
 padding:10px;
 clear:both;
 overflow:hidden;
}

.options_desc{
-moz-border-radius:8px 8px 8px 8px;
background:none repeat scroll 0 0 #F1F1F1;
color:#777777;
float:right;
padding:15px;
width:350px;
}

.labels{
 font-size:12px;
 display:block;
 margin-bottom:5px;
 font-weight:bold;
 color:#555;
}

label{
 font-size:12px;
 margin-bottom:5px;
 font-weight:bold;
 color:#555;
}

.options_input input[type="text"], .options_input select{
 width:275px;
 font-size:12px;
 padding:5px;
 color:#666;
 background:#FFF;
 border-color:#DFDFDF;
}
.options_input input:focus, .options_input textarea:focus{
 background:#fff;
}
.options_input textarea{
 width:275px;
 height:135px;
 padding:5px;
 color:#666;
 background:#FFF;
 border-color:#DFDFDF;
}

 span.submit{
 float:left;
 margin:0 30px 30px 0;
 padding:0;
 width:15%;
}

 .section_wrap span.submit{
 float:left;
 margin:0 20px 30px 30px;
 padding:0;
 width:15%;
}

The javascript file will be used to create jQuery functions for enhancing the themes page. If you don’t want jQuery, just remove the mention of it from the above function. Copy-paste the following in theme-options.js.

jQuery(document).ready(function($) {
 // hides as soon as the DOM is ready
 $( 'div.section_body' ).hide();
 // shows on clicking the noted link
 $( 'h3' ).click(function() {
 $(this).toggleClass("open");
 $(this).next("div").slideToggle( '1000' );
 return false;
 });

});

The theme-options.php is now ready. The complete code will read as follows:

<?php

// Theme Options
// Specky Geek -- http://www.speckygeek.com

$themename = "Jenny";
$shortname = "p2h";
$version = "1.0";

// Create theme options
global $options;
$options = array (

array( "name" => "General",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "Custom Feed URL",
 "desc" => "You can use your own feed URL (<strong>with http://</strong>). Paste your Feedburner URL here to let readers see it in your website.",
 "id" => $shortname."_feedurl",
 "type" => "text",
 "std" => get_bloginfo('rss2_url')),

array( "name" => "Delete Extra Feeds",
 "desc" => "WordPress adds feeds for categories, tags, etc., by default. Check this box to remove them and reduce the clutter.",
 "id" => $shortname."_cleanfeedurls",
 "type" => "checkbox",
 "std" => ""),

array( "name" => "Twitter ID'",
 "desc" => "Your Twitter user name, please. It will be shown in the navigation bar. Leaving it blank will keep the Twitter icon supressed.",
 "id" => $shortname."_twitterid",
 "type" => "text",
 "std" => ""),

array( "name" => "Facebook Page",
 "desc" => "Link to your Facebook page, <strong>with http://</strong>. It will be shown in the navigation bar. Leaving it blank will keep the Facebook icon suppressed.",
 "id" => $shortname."_facebookid",
 "type" => "text",
 "std" => ""),

array( "type" => "close"),

array( "name" => "Footer",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "Footer Text",
 "desc" => "Paste your text, copyright statements, etc., here.",
 "id" => $shortname."_footer_text",
 "type" => "textarea",
 "std" => ""),

array( "name" => "Analytics/Tracking Code",
 "desc" => "You can paste your Google Analytics or other website tracking code in this box. This will be automatically added to the footer.",
 "id" => $shortname."_analytics_code",
 "type" => "textarea",
 "std" => ""),

array( "type" => "close"),

array( "name" => "Advertisement Code",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "Adsense Code",
 "desc" => "Enter your Adsense code (or other ad network code) here.",
 "id" => $shortname."_adcode",
 "std" => "",
 "type" => "textarea"),

array( "type" => "close"),

);

function p2h_add_admin() {

    global $themename, $shortname, $options;

	if ( isset ( $_GET['page'] ) && ( $_GET['page'] == basename(__FILE__) ) ) {

		if ( isset ($_REQUEST['action']) && ( 'save' == $_REQUEST['action'] ) ){

			foreach ( $options as $value ) {
				if ( array_key_exists('id', $value) ) {
					if ( isset( $_REQUEST[ $value['id'] ] ) ) {
						update_option( $value['id'], $_REQUEST[ $value['id'] ]  );
					}
					else {
						delete_option( $value['id'] );
					}
				}
			}
		header("Location: admin.php?page=".basename(__FILE__)."&saved=true");
		}
		else if ( isset ($_REQUEST['action']) && ( 'reset' == $_REQUEST['action'] ) ) {
			foreach ($options as $value) {
				if ( array_key_exists('id', $value) ) {
					delete_option( $value['id'] );
				}
			}
		header("Location: admin.php?page=".basename(__FILE__)."&reset=true");
		}
	}

add_menu_page($themename, $themename, 'administrator', basename(__FILE__), 'p2h_admin');
add_submenu_page(basename(__FILE__), $themename . ' Options', 'Theme Options', 'administrator',  basename(__FILE__),'p2h_admin'); // Default
}

function p2h_add_init() {

$file_dir=get_bloginfo('template_directory');
wp_enqueue_style("p2hCss", $file_dir."/functions/theme-options.css", false, "1.0", "all");
wp_enqueue_script("p2hScript", $file_dir."/functions/theme-options.js", false, "1.0");

}

function p2h_admin() {

    global $themename, $shortname, $version, $options;
	$i=0;

	if ( isset ($_REQUEST['saved']) && ($_REQUEST['saved'] ) )echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings saved.</strong></p></div>';
	if ( isset ($_REQUEST['reset']) && ($_REQUEST['reset'] ) ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings reset.</strong></p></div>';

?>

<div class="wrap ">
<div class="options_wrap">
<h2 class="settings-title"><?php echo $themename; ?> Settings</h2>
<form method="post">

<?php foreach ($options as $value) {
switch ( $value['type'] ) {
case "section":
?>
	<div class="section_wrap">
	<h3 class="section_title"><?php echo $value['name']; ?></h3>
	<div class="section_body">

<?php
break;
case 'text':
?>

	<div class="options_input options_text">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		<input name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" value="<?php if ( get_option( $value['id'] ) != "") { echo stripslashes(get_option( $value['id'])  ); } else { echo $value['std']; } ?>" />
	</div>

<?php
break;
case 'textarea':
?>
	<div class="options_input options_textarea">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		<textarea name="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" cols="" rows=""><?php if ( get_option( $value['id'] ) != "") { echo stripslashes(get_option( $value['id']) ); } else { echo $value['std']; } ?></textarea>
	</div>

<?php
break;
case 'select':
?>
	<div class="options_input options_select">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		<select name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>">
		<?php foreach ($value['options'] as $option) { ?>
				<option <?php if (get_option( $value['id'] ) == $option) { echo 'selected="selected"'; } ?>><?php echo $option; ?></option><?php } ?>
		</select>
	</div>

<?php
break;
case "radio":
?>
	<div class="options_input options_select">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<span class="labels"><label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label></span>
		  <?php foreach ($value['options'] as $key=>$option) {
			$radio_setting = get_option($value['id']);
			if($radio_setting != ''){
				if ($key == get_option($value['id']) ) {
					$checked = "checked="checked"";
					} else {
						$checked = "";
					}
			}else{
				if($key == $value['std']){
					$checked = "checked="checked"";
				}else{
					$checked = "";
				}
			}?>
			<input type="radio" name="<?php echo $value['id']; ?>" value="<?php echo $key; ?>" <?php echo $checked; ?> /><?php echo $option; ?><br />
			<?php } ?>
	</div>

<?php
break;
case "checkbox":
?>
	<div class="options_input options_checkbox">
		<div class="options_desc"><?php echo $value['desc']; ?></div>
		<?php if(get_option($value['id'])){ $checked = "checked="checked""; }else{ $checked = "";} ?>
		<input type="checkbox" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" value="true" <?php echo $checked; ?> />
		<label for="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></label>
	 </div>

<?php
break;
case "close":
$i++;
?>
<span class="submit"><input name="save<?php echo $i; ?>" type="submit" value="Save Changes" /></span>
</div><!--#section_body-->
</div><!--#section_wrap-->

<?php break;
}
}
?>

<input type="hidden" name="action" value="save" />
<span class="submit">
<input name="save" type="submit" value="Save All Changes" />
</span>
</form>

<form method="post">
<span class="submit">
<input name="reset" type="submit" value="Reset All Options" />
<input type="hidden" name="action" value="reset" />
</span>
</form>
<br/>
</div><!--#options-wrap-->

</div><!--#wrap-->
<?php
}
add_action('admin_init', 'p2h_add_init');
add_action('admin_menu' , 'p2h_add_admin');
?>

Important: There is some problem with the way WordPress/plugin shows code. Please make sure that the quote within quotes have a (backslash) just before them.$checked = “checked=”checked””;

Even after we have written the entire code on theme-options.php, you won’t see any change in your WordPress because it hasn’t been hooked to the blogging platform yet. Open the theme’s functions.php file and paste the following code just below the <?php tag.

$functions_path = TEMPLATEPATH . '/functions/';
//Theme Options
require_once ($functions_path . 'theme-options.php');

WordPress has been instructed to use the theme-options.php file. Now, you can see your theme options page in the menu list on WordPress admin.

How to implement the customizations?

After being able to save options, we need some way to implement it in our theme. Here’s how we can use the feed link settings to show our custom URL and remove extra feeds from WordPress header. The following code can be added to theme-options.php or functions.php. It checks if the feed URL option is set. If yes, it adds the appropriate feed link to the header and removes the default link. If you have checked the option to delete extra feeds, it also removes them.

//Header Customizations
function p2h_wp_head() {
 //If Set in Theme Options, Add Feed URL in Head
 if(get_option('p2h_feedurl') != '') {
 echo '<link rel="alternate" type="application/rss+xml" href="'. get_option('p2h_feedurl') .'" title="'. get_bloginfo('name') .' RSS Feed"/>'."n";
}
}
add_action('wp_head','p2h_wp_head');

//Header Customization -- Remove Auto Feed URL
if(get_option('p2h_feedurl') != '') {
 // Remove the links to feed
 remove_action( 'wp_head', 'feed_links', 2);
}

// Remove the links to the extra feeds such as category feeds
if(get_option('p2h_cleanfeedurls') !='' ) {
remove_action( 'wp_head', 'feed_links_extra', 3 );
}

If you want to output the footer text in your theme, use the get_option() tag at appropriate place.

<?php if (get_option('p2h_footer_text') != '') { ?>
<?php echo(stripslashes (get_option('p2h_footer_text')));?>
<?php } ?>

You can use similar conditional statements to get your desired results. All that you need is some imagination.

Update: A reader Wyatt Kirby asked how he can dynamically add categories in the theme options menu. The code above is missing an example for implementing Select menu. Let’s see how can it be done both manually and dynamically.

Code to dynamically populate WordPress categories in theme options

$categories = get_categories('hide_empty=0&orderby=name');
$wp_cats = array();
foreach ($categories as $category_list ) {
       $wp_cats[$category_list->cat_ID] = $category_list->cat_name;
}
array_unshift($wp_cats, "Choose a category");

Now, you will have to add an “Options” variable in the options array as shown in the code below. Let’s see two implementations of Select menu—one with manually added options and the other with dynamically populated lists.

$categories = get_categories('hide_empty=0&orderby=name');
$wp_cats = array();
foreach ($categories as $category_list ) {
       $wp_cats[$category_list->cat_ID] = $category_list->cat_name;
}
array_unshift($wp_cats, "Choose a category");

// Create theme options
global $options;
$options = array (

array( "name" => "Select Menus",
 "type" => "section"),

array( "type" => "open"),

array( "name" => "Colour Scheme",
 "desc" => "Choose a colour scheme for your theme.",
 "id" => $shortname."_colourscheme",
 "type" => "select",
 "options" => array("Red", "Blue", "Green"),
 "std" => get_bloginfo('rss2_url')),

array( "name" => "Pick Categories",
 "desc" => "Choose a category from the list to do some interesting stuff.",
 "id" => $shortname."_categories",
 "type" => "select",
 "options" => $wp_cats,
 "std" => ""),

array( "type" => "close")
);

Update: Now that you know how to create a theme options page for WordPress themes, how about creating an even better one? Learn how to create an improved WordPress theme options page using the Settings API.

Comments

  1. Thank you for this tutorial, this clarifies how to actually implement this solution for 3.0. Also- not sure if this is noted here but the Jenny theme available free from this site had all of the source for this tutorial. Great work on that theme Pritam!

  2. Does the work perfectely for me. Thanks form Bulgaria

  3. thanks a lot for this tutorial. very long but I will try it.

  4. Thanks so much for this, i’ll certainly be using this in my upcoming projects!

  5. How on earth does this differ from the original code which you’ve copied almost word for word here: http://net.tutsplus.com/tutorials/wordpress/how-to-create-a-better-wordpress-options-panel/ ?

  6. Thanks for your reply.

    Neither your code nor the Net Tuts code uses a nonce or settings_fields as recommended in the Codex http://codex.wordpress.org/Creating_Options_Pages

    Is the code here guaranteed to get through any review process? I’ve searched the net high and low and to be honest the Codex is the only place where I’ve found the nonce or settings_fields used. And everyone seems to be regurgitating the same bit of code (as here and on Net Tuts) with one or two alterations, so it’s very hard to know who’s got it right.

    Cheers!

    • This is the code that I used for Jenny, a theme that is doing pretty well in the theme repository. I know now it is preferred to use the WP’s in-built theme options function to add the options. I have created another version of code based on that. Since the theme using the code is waiting for more than a couple of weeks for being reviewed, I don’t want to share it now. Once the theme is vetted, I will release the code.

  7. Thanks! Could you leave a notification and link on this page too, please?

    • Please subscribe to Specky Geek via RSS, Twitter or Facebook for updates. And, may I request that you use your real name and email next time. I don’t mind being criticized. :)

  8. Excellent article. Very well explained! I will recommend your site to all my friends.

    I just have a difficulty…

    You can add to the tutorial how to use checkbox in the choice of multiple categories?

    Thanls!

  9. the area of comments not accepted. Send me an email that I send you the code to post here.

  10. Great tutorial!

    You mentioned a better way to do this and that you were waiting on approval from WordPress.org before you posted the code. How did you go with that? I’d love to see this updated to reflect the new way to do theme options.

    Thanks!

    • Hi Drew, Welcome to Specky Geek! Thanks for reminding me. Shaan WordPress theme uses an improved options page. It has been included in the WordPress theme repository, but had some issues. A newer version is pending review and security audit. Once it is okayed, I will write a tutorial.

  11. How do I display radio buttons? The code below doesn’t work and returns “Warning: Invalid argument supplied for foreach()”

    array( “name” => “Favicon”,
    “desc” => “Choose a favicon”,
    “id” => $shortname.”_favicon”,
    “type” => “radio”,
    “std” => “”),

    • Hi Damien, I see that you have not supplied the options for the radio button. Thanks

      • Hey Pritam,
        How would the code look?

        array( "name" => "Page Alignment",
        "desc" => "How should the page be aligned?",
        "id" => $shortname."_page_alignment",
        "type" => "radio",
        "options" => "checked",
        "std" => "")

        Is that right? I don’t think it is.

        Thanks for the help,
        Drew

        • Hi Drew, You can look at Shaan WordPress theme. It uses an evolved version of the above theme options page. Maybe, I will publish it in the blog in the weekend. Thanks

  12. Thanks! I was having issues with pulling the theme options out of the functions.php file. But, now I’ve got it working thanks to your examples.

    Further tip, I was having issues with escaping single and double quotes. I ended up using wp_htmledit_pre() to escape textarea’s. I used esc_attr() for value=”…” in the input fields. And stripslashes_deep() before the update_option calls. (I can’t tell you how many themes I’ve seen that don’t escape quotes correctly.)

    I can post code if you need to see more. Or check out “wp-admin/options.php” for how WordPress does it.

    Thanks!

  13. Is there a simple way to make this theme options page submit via AJAX to eliminate page refreshing?

  14. Hi,
    I’m not a big coder but I’m trying to learn it.
    I created the theme-options.php, theme-options.css and theme-options.js and I uploaded them into the functions folder. After this I edited the functions.php so it gets hooked to the theme.
    When I go to the new options page I only see the “Save” and “Reset” buttons.
    Do I need to change or add something more to the theme-options.php to get all the options or am I missing something else?

    Thanks for the help

    • Please check your codes for any error(s). Alternatively, you can have a look at Shaan WordPress theme to see how i have implemented a theme options. It’s different from the one mentioned in the tutorial, but the basic concept is the same.

  15. Oh man! This tutorial is a lifesaver as compared to the WordPress Codex info on this stuff. Thanks so much for the post!

  16. WordPress 3.01 building a custom theme built on top of the Starkers blank theme. Getting the following error:
    Parse error: syntax error, unexpected T_STRING in /functions/theme-options.php on line 189

    Line 189 is copied straight from the tutorial, and is as follows:
    $checked = "checked="checked"";
    Confused. Any ideas? thanks!

  17. Please link download code script example? Tranks

  18. This is a great tutorial. I have implemented and it works like a charm. However, when I use the “Select” drop menu to choose the category, in the them, it shows the name of the category, for example, “WordPress Theme”. But I want it to display the ID of the category since I want to query post from that category. If possible, would you mind teaching me how to do it? Thank you!

    • If you go through the code, you will find that the category name is derived from the category ID. You can remove the portion which replaces category ID with their names

      • Thanks for the reply. I guess I made a few confusions here. I changed the code and it did display the ID of the category on the theme option page. But what I want to do is to display the ID of the category on the theme of the blog (and I can use it to display query of featured post from that category), not on the theme option page. Would you mind telling me how to do this again?

  19. Excellent tutorial Pritam,

    Does someone know how to allow html entitities in textfields, similar to how you can use them in the textarea?
    If I save a normal <a href=" etc to the textfield, it breaks when reading the value back into the field.

    I guess it's something to do with htmlentities, and adding slashes to quotes, etc before saving to the db?

  20. Hi pritam ;)

    i would to implement to the theme options 3 panels, each have a different categories.

    I have a problem with get categories link to print in my template ;)
    here are my code:

    array( "name" => "Panel 1",
    "desc" => "Choose a category from which featured panel are drawn",
    "id" => $shortname."_panel_1",
    "type" => "select",
    "options" => $wp_cat_link,
    "std" => "chose category"),

    i have no idea how to take a category link by name ;/
    in my template prints only a name of chosen cat ;(

    • The above code will create a select input field with names of categories. You can select and save it. You can call the value of the category in your theme. How you use it in your theme is up to you.

  21. NIce job…i will try this code..

    this code i need for my web…
    thanks lot

  22. is there a code to upload the image as a banner. Without having to enter the image url.
    Metabox as in order to upload images to the needs barner.
    Thank you, sorry if english is not good.
    regards

  23. Excellent tutorial. Very well thought through.

  24. hi there, I’m trying to use Textarea for Google Analytics code option. But why the result changing the code?
    From:

    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-29509388-1']);
    _gaq.push(['_trackPageview']);

    (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();

    to

    var _gaq = _gaq || [];
    _gaq.push([\'_setAccount\', \'UA-29509388-1\']);
    _gaq.push([\'_trackPageview\']);

    (function() {
    var ga = document.createElement(\'script\'); ga.type = \'text/javascript\'; ga.async = true;
    ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\';
    var s = document.getElementsByTagName(\'script\')[0]; s.parentNode.insertBefore(ga, s);
    })();

    sorry for double post

    • Hey! You can simply add a textarea for posting the analytics code or just any code. In your theme output this by ‘escaping the HTML’ part. You can see the usage in any of my WordPress themes available on this website for download: Shaan, undedicated or Jenny. Thanks

  25. hi,
    Does anybody know how to upload image(logo)from the theme option page, plz tell me.

    Thanks in advance

  26. Hey! How do you set the different style sheets? I added that selection box but it doesn’t detect different style sheets? Or how do you implement it into the header.php file?
    Thanks!

    • Hi JC, You need to read the stylesheets from a folder to create an options list. You can also add the stylesheet options manually. Now, output the stylesheet option in the header and display the relevant sylesheet file. You can download the Jenny theme to see the implementation of different stylesheets on a theme. Thanks

  27. hm… how to output code for categories in theme options in homepage for sticky post ? :-)

  28. Dear sir,
    This is a fantastic post for me. It is really really good for me.
    Anyway , I have an issue here. The textarea field are not supporting html tag. when i create a link on footer the link path going change . And when i used img tag then image are not showing . Can you please tell me how i can write html tag on text area field ?

    It will be big help.

    Regards
    Tonmoy

  29. Hey Pritam, Thanks for the tutorial, I am have an issue though, I found your tut from nettus, on theirs everything seemed to work fine but the js file wouldn’t load properly and reading through the comments I saw yours saying you’ve refined the code a bit, now I’ve tried and tried but I can’t seem to get yours to work could you take a look and see if anything is wrong?

    …. CODE DELETED ….

  30. Hi, nice options page..works well. How would I create a sign up form (newsletter style) within the options that could be added to say the footer.php of my theme and allows users to sign up to the letter using their email? Many Thanks

    • Hi Richard,

      It is fairly easy to implement this. Try downloading the “Squeeze Master” theme from SmartWebWorker.com. Please browse the WordPress Themes section or search over the site. You will find the answer in the codes.

      Stay in touch.

      Thanks,
      Pritam

  31. Hi! This code works perfect for me, thanks! But now I have a little question.

    I only can get options in the theme using that code in header.php:

    global $options;
    foreach ($options as $value) {
    if (get_settings( $value['id'] ) === FALSE) { $$value['id'] = $value['std']; } else { $$value['id'] = get_settings( $value['id'] ); }
    }

    But I can’t use it in functions.php. I have to put it into every function, so it is cloned code. What can I do? Thanks! :-)

Trackbacks

  1. [...] post: Create WordPress Theme Options Page | Specky Geek Posted in WordPress Themes « WordPress Review Theme | Niche Review Themes Both comments [...]

  2. [...] Create WordPress Theme Options Page (Specky Geek) [...]

  3. [...] post: Create WordPress Theme Options Page | Specky Geek Posted in WordPress Themes Tags: options, tutorial, WordPress « WordPress Plugin [...]