2

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.

5

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.

| improve this answer | |
2

CODE UPDATED WITH = ADD UNLIMITED SIDEBARS (JavaScript)

Create a function that register sidebars, using [register_sidebar][1], 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>'
        ));
    }
  }
}

UPDATED: 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][2]) You can improve it adding javascript to dynamic add fields.. Add unlimited sidebars admin page.

add_action( 'admin_menu', 'my_sidebar_plugin_menu' );

function my_sidebar_plugin_menu() {

add_theme_page( 'sidebar Plugin Options', 'Add Sidebar', 'manage_options', 'my-sidebar-unique-identifier', 'my_sidebar_plugin_options' );

 $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_sidebar_plugin_options() {

 wp_enqueue_script('jquery');
 wp_enqueue_script('custom_sidebar-js', get_template_directory_uri() . '/js/custom_sidebar.js');
 if ( !current_user_can( 'manage_options' ) )  {
    wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
  }
 ?>

 <div class="my-form">
    <div class="wrap">
 <h2>Add Custom Sidebars</h2>

 <form id="sidebars" method="post">

 <?php wp_nonce_field('my_custom_sidebars', 'my_custom_sidebars_nonce');
 $saved = get_option('my_theme_sidebars');
 $xx=get_option('my_theme_sidebars');
 //print_r($xx);
 $no=count($xx);
 ?>

 <div id="append">
 <p class="text-box">
        <label for="box1">Sidebar-<span class="box-number">1</span></label>
        <input type="text" name="custom_sidebars[]" value="<?php echo $xx[0]; ?>" id="box1" />
        <a href="#" class="remove-box">Remove</a>

    </p>

 <?php if($no>1){ 
    for($i=1;$i<$no;$i++){

 ?>     
 <p class="text-box"><label for="box' + n + '">Sidebar-<span class="box-number"><?php echo $i+1; ?></span></label> 
 <input type="text" name="custom_sidebars[]" value="<?php echo $xx[$i]; ?>" id="box' + n + '" /> 
 <a href="#" class="remove-box">Remove</a>
 </p>
 <?php }

 } ?></div>
 <!--<a class="add-box" href="#">Add More</a>-->
 <button type="button"  class="add-box">Add New Sidebar</button>

 </table>

 <input type="hidden" name="action" value="update" />
 <input type="hidden" name="page_options" value="no_of_sidebar,sidebar_names,boxes" />

 <p class="submit">
<input type="submit" class="button-primary clsSubmit" value="<?php _e('Save Changes') ?>" />
</p>


</form>
</div>
</div>
    <?php
}

function my_custom_sidebars_notice() {
echo '<div class="updated"><p>Sidebar(s) 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][3] 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.

UPDATED: Create a new JavaScript file for multi sidebars js/custom_sidebar.js

( function( $ ) {

$('.my-form .add-box').click(function(){

var n = $('.text-box').length + 1;
var box_html = $('<p class="text-box"><label for="box' + n + '">Sidebar-<span class="box-number">' + n + '</span></label> <input type="text" name="custom_sidebars[]" value="" id="box' + n + '" /> <a href="#" class="remove-box">Remove</a></p>');
    box_html.hide();
    $('#append').append(box_html);
    box_html.fadeIn('slow');

    return false;


}); 

$('.my-form').on('click', '.remove-box', function(){
$(this).parent().css( 'background-color', '#FF6C6C' );
$(this).parent().fadeOut("slow", function() {
    $(this).remove();
    $('.box-number').each(function(index){
        $(this).text( index + 1 );
    });
});
return false;
});



$('.clsSubmit').click(function(){
var m = $('.text-box').length;
if(m==0){alert("press OK to Reset");}
});

Finally in your pages and posts just call get_sidebar(); as usual.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.