0
votes

Just wondering if someone could give me some advice on how to create unlimited sidebars for a WordPress theme.

So, basically I am looking into adding a meta box on posts and pages with a drop down list of all available sidebars, where the user can then select a specific sidebar for any post or page. This part I have figured out, however I would also like to add functionality here to allow users to create custom sidebars for any post or page. So, essentially the user could choose any sidebar for any post or page or create new sidebars for any post or page which then could be filled with widgets on the widgets page.

I half there, just not sure how to go about creating the functionality to create new sidebars.

2

2 Answers

0
votes

Giving the users option to choose a sidebar is fine, but i dont think its a good idea to give them functionality to create their own sidebars. You will quickly get into the problem where you will have tons of sidebars in your widget area each for a different post.

However if i was in your situation, i would have created a single sidebar and then dynamically added widgets to this sidebar depending on the post that is being viewed. For the end user both will look the same. Anyways there is no right or wrong answer here, it depends on how you want to tackle the situation.

0
votes

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.