How to add an options form to a wordpress theme using settings_fields

I spent some time today modifying a WordPress theme to take configuration properties.

I want one theme that I can quickly re-configure to create multiple blogs along different topics with different color/graphic schemes. I want easy maintenance so I’d love to share one instance of the theme across these different instances.

We’re using enough different plugins that WordPress Mu isn’t yet worth fighting. So database options and the Settings API seemed the best way.

The documentation on how to extend a theme this way is not so easy to find but there are plenty of examples. They tend to break the process into steps but don’t give as much sense of what you actually get and how to use it.

I based my code on this example:

After the fact, I found this description which seems well written:

I created a menu item and a corresponding properties form:

Wordpress Theme Options FormWordpress Theme Menu Item

My form adds three properties which are stored in the WordPress wp_options table and easily exposed on template pages

<link rel="stylesheet" href="<?php $options = get_option('vertical'); echo $options['vertical_custom_css_url']; ?>" type="text/css" media="screen" />

Here’s the actual code I added to the functions.php page of the theme. If you don’t have a functions.php you can just create one in your theme folder. You need to make sure the code below is wrapped in “<?php” “?>” tags.

//encapsulate the logic into a class
$cpanel = new ControlPanel();

class ControlPanel {
/* static array to contain default values
the values set an additional css to override standard css in the theme
as well as an image and link that is rendered in the sidebar. These
three settings allow me to use the same theme with minor variations
on different blogs on different topics but with very similar looks and feels */

var $default_settings = Array(
‘vertical_custom_css_url’ => ,
‘topic_banner_img’ => ‘/images/banner.jpg’,
‘topic_url’ => ‘’

function ControlPanel()
//hook to add a menu item in the Theme’s area of the admin sidebar
add_action(‘admin_menu’, array(&$this, ‘vertical_admin_menu’));
/* if options are not already created in the database, add them and set to default values
this creates a single database entry in wp_options with key vertical and
values a hash of key/value pairs */

if (!is_array(get_option(‘vertical’)))
add_option(‘vertical’, $this->default_settings);
//load the existing options into an array accessible as a property of this instance of ControlPanel
$this->options = get_option(‘vertical’);
//the function that ties an html form to the hook defined in the constructor.
function vertical_admin_menu() {
add_theme_page(‘Vertical Theme Control Panel’, ‘Customize Theme’, ‘edit_themes’, “vertical”, array(&$this, ‘vertical_theme_page’));
//function that defines the form for viewing and setting properties for the theme.
function vertical_theme_page() {
//if the form is being submitted, update the options in the database
if ( isset( $_POST[‘submit’] ) ) {
//if the “Save Changes” button was clicked, set the user entered values from the form
if (‘Save Changes’ == $_POST[‘submit’]) {
$this->options[“vertical_custom_css_url”] = $_POST[‘vertical_custom_css_url’];
$this->options[“topic_banner_img”] = $_POST[‘topic_banner_img’];
$this->options[“topic_url”] = $_POST[‘topic_url’];
} //else if “Defaults” was clicked, reset values to default
else if (‘Defaults’ == $_POST[‘submit’]) {
$this->options[“vertical_custom_css_url”] = $this->default_settings[‘vertical_custom_css_url’];
$this->options[“topic_banner_img”] = $this->default_settings[‘topic_banner_img’];
$this->options[“topic_url”] = $this->default_settings[‘topic_url’];
$state=“reverted to defaults”;
} //commit the changes to the database
update_option(‘vertical’, $this->options);
//render a status message of the above actions in the standard WordPress admin dialog box at the top of the form.
echo ‘<div class=“updated fade” id=“message” style=“background-color: rgb(255, 251, 204); width: 300px; margin-left: 20px”><p>Settings <strong>‘.$state.’</strong>.</p></div>‘;
//the actual html form in standard markup to appear standard in the WordPress Admin
<div class=‘wrap’>
<h2><?php _e(‘Customize Vertical Theme’); ?></h2>
<div id=“header”>
<div id=“headwrap”>
<div id=“header”>
<div id=“headerimg”>
<h1><?php bloginfo(‘name’); ?></h1>
<div class=“description”><?php bloginfo(‘description’); ?></div>
<form id=“vertical-settings-form” method=“post” action=“”>
<?php settings_fields( ‘vertical-settings’ ); ?>
<table class=“form-table”>
<tr valign=“top”>
<th scope=“row”>Path to Vertical CSS file:</th>
<input size=“70” type=“text” name=“vertical_custom_css_url” id=“vertical_custom_css_url” value=<?php echo $this->options[“vertical_custom_css_url”]; ?>” />
<br/><small>example: <?php echo(str_replace(get_bloginfo(‘url’),“”,get_bloginfo(‘template_url’).‘/’.str_replace(” “, “-“,strtolower(wptexturize(get_bloginfo( ‘name’ )))))); ?>/style.css</small>
<tr valign=“top”>
<th scope=“row”>Path to Category Page:</th>
<input size=“70” type=“text” name=“topic_url” id=“topic_url” value=<?php echo $this->options[“topic_url”]; ?>” />
<tr valign=“top”>
<th scope=“row”>Path to Category Banner:</th>
<input size=“70” type=“text” name=“topic_banner_img” id=“topic_banner_img” value=<?php echo $this->options[“topic_banner_img”]; ?>” />
<br/><small>example: <?php echo(str_replace(get_bloginfo(‘url’),“”,get_bloginfo(‘template_url’).‘/’.str_replace(” “, “-“,strtolower(wptexturize(get_bloginfo( ‘name’ )))))); ?>/images/banner.jpg</small>
<p class=“submit”>
<input type=“submit” name=“submit” class=“button-primary” value=<?php _e(‘Save Changes’) ?> />
<input type=“submit” name=“submit” class=“button-primary” value=<?php _e(‘Defaults’) ?> />
<input type=“hidden” name=“saved” value=“true”>

This entry was posted in software development and tagged , , , , , by Ken Judy. Bookmark the permalink.

About Ken Judy

I am an executive manager, software developer, father and husband trying to do more good than harm. I am an agile practitioner. I say this fully aware I say nothing. Sold as a tool to solve problems, agile is more a set of principles that encourage us to confront problems. Broad adoption of the jargon has not resulted in wide embrace of these principles. I strive to create material and human good by respecting co-workers, telling truth to employers, improving my skills, and caring for the people affected by the software I help build.