I’m creating a WordPress theme and I’ve noticed that a lot of premium themes allow the users to go to Appearance->Sidebars and create a new Sidebar by simply giving it a name.
The user can then Go to widgets and assign different widgets to this sidebar and also add custom menus. This I believe is a great feature as it allows users to have different sidebars on different pages.
Now I’m familiar with Custom Post Type and Theme options and know how I would let people choose a different sidebar for different pages, but I’m just having problems in creating the first step, which is to allow people to create a sidebar on their own. Do I need to create a CPT for this? or is there some other way?
I’ve searched a lot and the best thing I came across was a plugin, which has a lot of code and does too many things and for which I cannot even find the license info.
So please advice how I can create something like this and thank you very much.
2 Answers
Create a function that register sidebars, using register_sidebar
, starting from an option:
add_action('widgets_init', 'my_custom_sidebars');
function my_custom_sidebars() {
$sidebars = get_option('my_theme_sidebars'); // get all the sidebars names
if ( ! empty($sidebars) ) {
// add a sidebar for every sidebar name
foreach ( $sidebars as $sidebar ) {
if ( empty($sidebar) ) continue;
register_sidebar(array(
'name' => $sidebar,
'id' => sanitize_title($sidebar),
'before_title' => '<h1>',
'after_title' => '</h1>'
));
}
}
}
Now you have to save an option 'my_theme_sidebars'
that contain an array of sidebars name.
Here I’m posting post the code that create a page with 10 text inputs where add the sidebar name. (I’ll use add_theme_page
) You can improve it adding javascript to dynamic add fields..
add_action('admin_menu', 'my_custom_sidebars_page');
function my_custom_sidebars_page() {
add_theme_page(
'Sidebars',
'Sidebars',
'edit_theme_options',
'my_custom_sidebars',
'my_custom_sidebars_page_print'
);
// save the form if submitted
$nonce = filter_input(INPUT_POST, 'my_custom_sidebars_nonce', FILTER_SANITIZE_STRING);
if ( ! empty($nonce) && wp_verify_nonce($nonce, 'my_custom_sidebars') ) {
$sidebars = (array) $_POST['custom_sidebars'];
update_option('my_theme_sidebars', $sidebars);
add_action('admin_notices', 'my_custom_sidebars_notice');
}
}
function my_custom_sidebars_page_print() {
if (! current_user_can('edit_theme_options') ) return;
?>
<div class="wrap">
<h2>Sidebars</h2>
<form id="sidebars" method="post">
<?php
wp_nonce_field('my_custom_sidebars', 'my_custom_sidebars_nonce');
$saved = get_option('my_theme_sidebars');
for ($i=0; $i<10; $i++) {
$value = isset( $saved[$i] ) ? esc_attr($saved[$i]) : '';
?>
<input type="text" name="custom_sidebars[]" value="<?php echo $value;?>" />
<?php } ?>
<p class="submit">
<input name="submit" class="button button-primary" value="Save" type="submit">
</p>
</form>
</div>
<?php
}
function my_custom_sidebars_notice() {
echo '<div class="updated"><p>Updated.</p></div>';
}
Now, you have you let users select the sidebars for a specific page.
You can add a metabox for that. (See add_meta_box
docs).
add_action( 'add_meta_boxes', 'my_custom_sidebar_metabox' );
function my_custom_sidebar_metabox() {
$screens = array( 'post', 'page' ); // add the metabox for pages and post
foreach ( $screens as $screen ) {
add_meta_box('my_custom_sidebar', 'Select a Sidebar','my_custom_sidebar_box', $screen);
}
}
function my_custom_sidebar_box( $post ) {
$sidebars = get_option('my_theme_sidebars'); // get all the sidebars names
if ( empty($sidebars) ) {
echo 'No custom sidebars registered.';
return;
}
wp_nonce_field( 'my_custom_sidebar', 'my_custom_sidebar_box_nonce' );
$value = get_post_meta( $post->ID, '_custom_sidebar', true ); // actual value
echo '<label>Select a Sidebar</label> ';
echo '<select name="custom_sidebar">';
// default option
echo '<option value=""' . selected('', $value, false) . '>Default</option>';
// an option for every sidebar
foreach ($sidebars as $sidebar) {
if ( empty($sidebar) ) continue;
$v = sanitize_title($sidebar);
$n = esc_html($sidebar);
echo '<option value="' . $v . '"' . selected($v, $value) .'>' .$n .'</option>';
}
echo '<select>';
}
Then add the function to save the metabox:
add_action( 'save_post', 'my_custom_sidebar_metabox_save' );
function my_custom_sidebar_metabox_save( $post_id ) {
// If this is an autosave, our form has not been submitted, do nothing.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
// check nonce
$nonce = filter_input(INPUT_POST, 'my_custom_sidebar_box_nonce', FILTER_SANITIZE_STRING);
if ( empty($nonce) || ! wp_verify_nonce( $nonce, 'my_custom_sidebar' ) ) return;
$type = get_post_type($post_id);
// Check the user's permissions.
$cap = ( 'page' === $type ) ? 'edit_page' : 'edit_post';
if ( ! current_user_can( $cap, $post_id ) ) return;
$custom = filter_input(INPUT_POST, 'custom_sidebar', FILTER_SANITIZE_STRING);
// Update the meta field in the database.
if ( empty($custom) ) {
delete_post_meta( $post_id, '_custom_sidebar');
} else {
update_post_meta( $post_id, '_custom_sidebar', $custom );
}
}
In this way your users can choose a custom sidebar for every post or page. It is saved in the meta field ‘_custom_sidebar'
.
To display the custom sidebar, your sidebar.php
should contain something like:
// change the following according to your defaults sidebar if exists
$sidebar="main_sidebar";
// if in singular post/page check for saved custom sidebar
if ( is_singular() ) {
$id = get_queried_object_id(); // get current post/page id
$custom = get_post_meta( $id, '_custom_sidebar', true ); // get selected sidebar
if ( ! empty($custom) ) $sidebar = $custom;
}
if ( is_active_sidebar( $sidebar ) ) {
?>
<ul id="sidebar"><?php dynamic_sidebar( $sidebar ); ?></ul>
<?php } ?>
Finally in your pages and posts just call get_sidebar();
as usual.