Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

How to Use Custom Sidebars on Posts and Pages

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

Today I'd like to show you how to easily add custom sidebars to use within your posts and pages. It could be useful to display different widgets according to your page or post's topic.

We'll see how to use WordPress meta boxes to store and retrieve a chosen sidebar for a specific post. Custom sidebars will be added in the theme options section.


Introduction

I used to deal with the great widget logic plugin to display various widgets on different pages, but the widgets page became very fuzzy and difficult to maintain. So why not use several sidebars and choose which one to display on a specific post? That's what I'll cover in this tutorial.


Step 1 Adding Sidebars in the Theme Options Page (Twenty Eleven)

In this tutorial, I'll use the great WordPress default theme Twenty Eleven to demonstrate how to use custom sidebars in your theme.

First, we are going to add a new setting in Appearance -> Theme options. You can refer to this great tutorial to see how to add settings.

Open the theme-options.php file, located in twentyeleven/inc and add this code at the end of the twentyeleven_theme_options_init() function:

add_settings_field( 'custom_sidebar', __( 'Custom sidebars', 'twentyeleven' ), 'twentyeleven_settings_field_custom_sidebar', 'theme_options', 'general' );

Then add a default value (an empty array) to the default theme options values, at the end of the twentyeleven_get_default_theme_options() function:

$default_theme_options = array(
	'color_scheme' => 'light',
	'link_color'   => twentyeleven_get_default_link_color( 'light' ),
	'theme_layout' => 'content-sidebar',
	'custom_sidebar' => array()
);

Now we are going to create the callback function that handles the setting's display.

Let's add some jQuery to handle interactions such as adding and removing sidebars, which are basically some list elements containing a hidden input. We'll also generate those list elements from already saved sidebars.

function twentyeleven_settings_field_custom_sidebar()
{
	// Retrieve theme options
	$opts = twentyeleven_get_theme_options();

	// A bit of jQuery to handle interactions (add / remove sidebars)
	$output = "<script type='text/javascript'>";
	$output .= '
				var $ = jQuery;
				$(document).ready(function(){
					$(".sidebar_management").on("click", ".delete", function(){
						$(this).parent().remove();
					});
					
					$("#add_sidebar").click(function(){
						$(".sidebar_management ul").append("<li>"+$("#new_sidebar_name").val()+" <a href=\'#\' class=\'delete\'>'.__("delete", $themename).'</a> <input type=\'hidden\' name=\'twentyeleven_theme_options[custom_sidebar][]\' value=\'"+$("#new_sidebar_name").val()+"\' /></li>");
						$("#new_sidebar_name").val("");
					})
					
				})
	';
	
	$output .= "</script>";

	$output .= "<div class='sidebar_management'>";
	
	$output .= "<p><input type='text' id='new_sidebar_name' /> <input class='button-primary' type='button' id='add_sidebar' value='".__("add", $themename)."' /></p>";
	
	$output .= "<ul>";

	// Display every custom sidebar
	if(isset($opts['custom_sidebar']))
	{
		$i = 0;
		foreach($opts['custom_sidebar'] as $sidebar)
		{
			$output .= "<li>".$sidebar." <a href='#' class='delete'>".__("delete", $themename)."</a> <input type='hidden' name='twentyeleven_theme_options[custom_sidebar][]' value='".$sidebar."' /></li>";
			$i++;
		}
	}
	
	$output .= "</ul>";
	
	$output .= "</div>";
	
	echo $output;
}

Eventually, add this code in the twentyeleven_theme_options_validate() function to sanitize and validate form input:

if ( isset( $input['custom_sidebar'] ) ) {
	$output['custom_sidebar'] = $input['custom_sidebar'];
}

At this point, you should be able to manage and save custom sidebars within your theme. For instance, let's create a new custom sidebar called "My custom sidebar". Your theme options page should look like this:

Managing custom sidebars in the theme options section

Step 2 Register Custom Sidebars

Now we're able to add custom sidebars, we need to register them so they can appear in the widgets admin page.

In the Twenty Eleven theme, this is done within the twentyeleven_widgets_init() function. So at the end of this function add this:

$options = twentyeleven_get_theme_options();

if(isset($options['custom_sidebar']) && sizeof($options['custom_sidebar']) > 0)
{
	foreach($options['custom_sidebar'] as $sidebar)
	{
		register_sidebar( array(
			'name' => __( $sidebar, 'twentyeleven' ),
			'id' => generateSlug($sidebar, 45),
			'before_widget' => '<aside id="%1$s" class="widget %2$s">',
			'after_widget' => "</aside>",
			'before_title' => '<h3 class="widget-title">',
			'after_title' => '</h3>',
		) );
	}
}

We retrieve theme options, check that there is at least one custom sidebar and register it. We use a quick function to generate a slug out of the sidebar name to be used as the sidebar ID.

function generateSlug($phrase, $maxLength)
{
	$result = strtolower($phrase);

	$result = preg_replace("/[^a-z0-9\s-]/", "", $result);
	$result = trim(preg_replace("/[\s-]+/", " ", $result));
	$result = trim(substr($result, 0, $maxLength));
	$result = preg_replace("/\s/", "-", $result);

	return $result;
}

Now, go to Appearance -> Widgets and you should see our new custom sidebar.

Add widgets to custom sidebars

Step 3 Adding A Meta Box

Now our custom sidebars are available, we'll add a meta box to display a list of all sidebars available inside the post editing form.

If you're not familiar with meta boxes, you can refer to these links:

Now let's dig into the code.

Add Meta Boxes

First, we'll simply add our meta boxes. We need to declare two meta boxes, one for posts and one for pages. We also need to register two hooks, one to add meta boxes and the other one to save them.

So open your functions.php file and add this:

/* Define the custom box */

add_action( 'add_meta_boxes', 'add_sidebar_metabox' );
add_action( 'save_post', 'save_sidebar_postdata' );

/* Adds a box to the side column on the Post and Page edit screens */
function add_sidebar_metabox()
{
	add_meta_box( 
		'custom_sidebar',
		__( 'Custom Sidebar', 'twentyeleven' ),
		'custom_sidebar_callback',
		'post',
		'side'
	);
	add_meta_box( 
		'custom_sidebar',
		__( 'Custom Sidebar', 'twentyeleven' ),
		'custom_sidebar_callback',
		'page',
		'side'
	);
}

Create the Callback Function

Now, let's create the custom_sidebar_callback function, which will print out the meta boxes' markup.

There're several key steps in this function:

  • Retrieve all registered sidebars (theme default sidebars included) with the global $wp_registered_sidebars variable.
  • Get post metas
  • Create nonce security
  • Add a select element with all sidebars plus a default one which is defined directly in the template file.
/* Prints the box content */
function custom_sidebar_callback( $post )
{
	global $wp_registered_sidebars;
	
	$custom = get_post_custom($post->ID);
	
	if(isset($custom['custom_sidebar']))
		$val = $custom['custom_sidebar'][0];
	else
		$val = "default";

	// Use nonce for verification
	wp_nonce_field( plugin_basename( __FILE__ ), 'custom_sidebar_nonce' );

	// The actual fields for data entry
	$output = '<p><label for="myplugin_new_field">'.__("Choose a sidebar to display", 'twentyeleven' ).'</label></p>';
	$output .= "<select name='custom_sidebar'>";

	// Add a default option
	$output .= "<option";
	if($val == "default")
		$output .= " selected='selected'";
	$output .= " value='default'>".__('default', $themename)."</option>";
	
	// Fill the select element with all registered sidebars
	foreach($wp_registered_sidebars as $sidebar_id => $sidebar)
	{
		$output .= "<option";
		if($sidebar_id == $val)
			$output .= " selected='selected'";
		$output .= " value='".$sidebar_id."'>".$sidebar['name']."</option>";
	}
  
	$output .= "</select>";
	
	echo $output;
}

Save Meta Box

Now let's save our post meta. Again several steps here:

  • Check WordPress is not autosaving
  • Check nonce and authorizations
  • Save post_meta
/* When the post is saved, saves our custom data */
function save_sidebar_postdata( $post_id )
{
	// verify if this is an auto save routine. 
	// If it is our form has not been submitted, so we dont want to do anything
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
	  return;

	// verify this came from our screen and with proper authorization,
	// because save_post can be triggered at other times

	if ( !wp_verify_nonce( $_POST['custom_sidebar_nonce'], plugin_basename( __FILE__ ) ) )
	  return;

	if ( !current_user_can( 'edit_page', $post_id ) )
		return;

	$data = $_POST['custom_sidebar'];

	update_post_meta($post_id, "custom_sidebar", $data);
}

Now you should now be able to see this box in the post edit page, in the right column. If not, check that the custom sidebar box is displayed in the top screen options panel.

Choosing a sidebar in the custom sidebar meta box

Step 4 Adjust Template Files

Now everything is correctly set up, what's left to do is updating our templating files so that they can display custom sidebars.

Let's create a new page based on the sidebar template (available in the page attributes box). This template relies on the sidebar-page.php file. Edit this file and add these lines at the top (below the template's commented header):

$options = get_post_custom(get_the_ID());

if(isset($options['custom_sidebar']))
{
	$sidebar_choice = $options['custom_sidebar'][0];
}
else
{
	$sidebar_choice = "default";
}

We retrieve current post meta data to get the chosen sidebar.

To switch between a custom sidebar and the default one, change the get_sidebar() call at the bottom of this same file to this:

if($sidebar_choice && $sidebar_choice != "default")
{
	get_sidebar("custom");
}
else
{
	get_sidebar();
}

The get_sidebar($slug) calls for sidebar-slug.php. So what we have to do, is to create a file named sidebar-custom.php and add this inside:

$options = get_post_custom($post->ID);
$sidebar_choice = $options['custom_sidebar'][0];

?>
<aside id="sidebar" class="floatleft">
	
	<ul class="widgets">
		<?php if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar() ) : 
			dynamic_sidebar($sidebar_choice);
		else : 
			/* No widget */
		endif; ?>
	</ul>

</aside>

Now your page should display the sidebar you chose. For instance, I added two widgets in my custom sidebar:

Page with custom sidebar

I won't cover how to apply this to posts as it's exactly the same behaviour, you just have to update the content-single.php file to manage custom sidebars.


Conclusion

That's all folks! Now you can use unlimited sidebars for your pages and posts. This is just one solution among others, but it's a quick and easy way to implement custom sidebars, so don't hesitate to leave a comment, share your ideas, and give feedback!

Advertisement