0

I am trying to create one sidebar area per page in a WordPress site. For example, if a WordPress installation has 2 pages: 'Home' and 'Blog', then there'll be two sidebar areas, 'Home sidebar area' and 'Blog sidebar area'. I thought I could just loop through the pages and create the sidebar areas dynamically, like so:

// functions.php
add_action( 'widgets_init', 'xxx_widgets_init' );
function xxx_widgets_init() {

    $args = array( 'post_type' => 'page' );

    $the_query = new WP_Query( $args );

    if ( $the_query->have_posts() ) {

        while ( $the_query->have_posts() ) {

            $the_query->the_post();

           register_sidebar( array(
             'name'          =>  'Widget name',
             'id'            => 'widget-id-' . $post->ID,
             'description'   => __( 'Widget desc', 'xxx' ),
             'before_widget' => '<div>',
             'after_widget'  => '</div>',
             'before_title'  => '',
             'after_title'   => '',
           ) );

        }

        //Restore original Post Data
        wp_reset_postdata();

    }

}

This works, I can see one sidebar area per page. Furthermore, if I create a third page, the third sidebar area gets instantly created without issues, as expected.

I go to appearances > widgets, and add a few widgets to my dynamic sidebar areas, and they get saved successfully.

The issue is, there is a unexpected behavior when doing this exact same thing, but in the theme customizer:

If I go to the Customizer > Widgets > [I can see my widget areas here OK] > ... If I try to add a widget, what appears to be an infinite autosave is triggered, and it's not possible to add, edit or move widgets around. Can you tell if there's anything wrong with this approach to create dynamic widget areas ?

  • Wouldn't this create a sidebar area for each post on an archive page, such as Blog? – Nathan Powell Oct 18 '16 at 2:17
  • @NathanPowell it is my understanding that the following line "$args = array( 'post_type' => 'page' );" targets only the pages – LCabezal Oct 18 '16 at 2:38
0

Creating new query objects is not a good idea in this situation. Try simply getting the pages and using those objects to serve up the widget areas:

add_action( 'widgets_init', 'my_243057_widgets_init' );

function my_243057_widgets_init() {

    /**
     * Get only published page objects
     * @link: https://codex.wordpress.org/Function_Reference/get_pages
     */
    $pages = get_pages();

    foreach ( $pages as $page ) {

        register_sidebar( array(
            'name'          =>  'Widget name',
            'id'            => 'widget-id-' . $page->ID,
            'description'   => __( 'Widget for page: ' . $page->post_title ),
            'before_widget' => '<div>',
            'after_widget'  => '</div>',
            'before_title'  => '',
            'after_title'   => '',
        ) );
    }
}
  • This works indeed, any idea why it is not possible to do it inside a loop ? -- Thanks for the help. – LCabezal Oct 18 '16 at 3:47
  • Basically "The Loop" is intended for templates and display from what I understand. I don't use it much, so I can't really explain. – Nathan Powell Oct 18 '16 at 3:54
  • Essentially the have_posts() method of that object screws this up. – Nathan Powell Oct 18 '16 at 3:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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