There is a way to do it but it's a bit lengthy.
Create a customizer control to add multiple sidebars
The easiest way is to just take the custom control called Multi Input field from here. Also, be sure to add this custom control, and all the jQuery functionality that goes with it (in the .js file).
With that, add to your customizer file (or if you don't have a dedicated customizer file, to your functions.php file)
if(!function_exists('yourtheme_text_sanitization')){
function yourtheme_text_sanitization($input){
return wp_kses_post( force_balance_tags($input) );
}
}
/**
------------------------------------------------------------
SECTION: Sidebars
------------------------------------------------------------
**/
$wp_customize->add_section('section_sidebars', array(
'title' => esc_html__('Sidebars', 'yourtheme'),
'priority' => 0,
));
/**
Sidebars
**/
$wp_customize->add_setting('sidebars', array(
'default' => '',
'sanitize_callback' => 'yourtheme_text_sanitization',
));
$wp_customize->add_control(new Multi_Input_Custom_control($wp_customize, 'sidebars', array(
'label' => esc_html__( 'Sidebars', 'yourtheme' ),
'description' => esc_html__( 'Add as many custom sidebars as you need', 'yourtheme' ),
'settings' => 'sidebars',
'section' => 'section_sidebars',
)));
The first function is the sanitization function for your customizer sanitization callback.
So now you should have 'Sidebars' in your Appearance > Customize menu.
Create sidebars dynamically
But now you need to add your sidebars. If you have a dedicated sidebar file like sidebars.php where you register your theme sidebars, you can put this there, or in your functions.php file
if ( function_exists( 'register_sidebar' ) ) {
$sidebars=get_theme_mod('sidebars','');
if($sidebars!=''){
$sidebars = explode('|', $sidebars);
$i = 0;
foreach($sidebars as $sidebar){
$i++;
register_sidebar(array(
'name'=>$sidebar,
'id' => 'sidebar-'.$i,
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<div class="sidebar-widget-heading"><h3>',
'after_title' => '</h3></div>',
));
}
}
}
This is the minimum you need so that you can add multiple sidebars in the theme, and they should appear in Appearance > Widgets.
Add sidebar metabox
Now adding a metabox to display them is relatively easy. In your functions.php, or a separate file where you add metaboxes to posts/pages/CPT, add
// Add metabox
add_action('admin_init', 'yourtheme_post_add_meta');
if ( ! function_exists( 'yourtheme_post_add_meta' ) ){
function yourtheme_post_add_meta(){
add_meta_box('post-sidebar', esc_html__('Select Sidebar', 'yourtheme'), 'yourtheme_post_sidebar_meta_box', 'post');
}
}
//Metabox
if ( ! function_exists( 'yourtheme_post_sidebar_meta_box' ) ){
function yourtheme_post_sidebar_meta_box( $post ){
$values = get_post_custom( $post->ID );
$custom_sidebar = (isset($values['custom_sidebar'][0])) ? $values['custom_sidebar'][0] : '';
wp_nonce_field( 'my_meta_box_sidebar_nonce', 'meta_box_sidebar_nonce' );
?>
<p>
<select name="custom_sidebar" id="custom_sidebar">
<?php
global $wp_registered_sidebars;
$sidebar_replacements = $wp_registered_sidebars;
if(is_array($sidebar_replacements) && !empty($sidebar_replacements)){
foreach($sidebar_replacements as $sidebar){
echo "<option value='{$sidebar['name']}'".selected($sidebar['name'], $custom_sidebar, false).">{$sidebar['name']}</option>";
}
}
?>
</select>
</p>
<?php
}
}
//Save Metabox
add_action( 'save_post', 'yourtheme_post_save_sidebar_meta_box' );
if ( ! function_exists( 'yourtheme_post_save_sidebar_meta_box' ) ){
function yourtheme_post_save_sidebar_meta_box( $post_id ){
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
return;
}
if( !isset( $_POST['custom_sidebar'] ) || !wp_verify_nonce( $_POST['meta_box_sidebar_nonce'], 'my_meta_box_sidebar_nonce' ) ) {
return;
}
if( !current_user_can( 'edit_pages' ) ) {
return;
}
if( isset( $_POST['custom_sidebar'] ) ){
update_post_meta( $post_id, 'custom_sidebar', wp_kses( $_POST['custom_sidebar'] ,'') );
}
}
}
And this should be it. A bit lengthy, but a way to add as many sidebars to your theme as you wish :)
Hope it helps.