Retrieve each widget separately from a sidebar

I would like to retrieve each widget existing in a sidebar in order e.g. to mix them with posts inside the main loop.

I know I can use different widget areas (sidebars) but this approach clutters the widget admin page with some tens of sidebars. To mitigate this, I thought to just add them to a single sidebar and retrieve them consecutively when needed.

Read More

But I’m stuck. I’ve no idea on how to retrieve a widget separately.

My tentative approach is to use wp_get_sidebars_widgets and the_widget but I’m not able to retrieve the widget class name.

Here is a simplified snippet of my code. In this case I’m trying to add a widget every three posts, but is an oversimplification of the logic (since I do not want just to add them regularly) in order to provide you the idea. I’d like to visualize every widget using the_widget or any other function. How can I accomplish this? Is it possible?

    <?php 
    $i = 1;
    $widgets = wp_get_sidebars_widgets(); // I KNOW THE USE OF THIS IS DISCOURAGED (PRIVATE) BUT CANNOT FIND ALTERNATIVES. 
    if ( have_posts() ) : ?>

        <?php while ( have_posts() ) : the_post(); ?>

            <?php
                if ($i%3 == 0){
                    echo "<h1>WIDGET #".($i/3)."</h1>";
                    the_widget($widgets['homepage-1'][$i/3]); // THIS DOES NOT WORKS SINCE I'M NOT GIVING THE CLASS NAME. HOW TO RETRIEVE IT?
                }
                get_template_part( 'content', get_post_format() );
                $i++;
            ?>

        <?php endwhile; ?>

        <?php _s_paging_nav(); ?>

    <?php else : ?>

        <?php get_template_part( 'content', 'none' ); ?>

    <?php endif; ?>

Related posts

2 comments

  1. I am taking the core of the question to be: “… I’m not able to retrieve the widget class name”

    You will need to check the global variable $wp_registered_widgets to fill in the missing information. This proof-of-concept code should give you the idea. The code assumes a sidebar named sidebar-1. You will have to adjust that.

    global $wp_registered_widgets;
    $widgets = wp_get_sidebars_widgets(); 
    var_dump($widgets['sidebar-1']); // dump the data
    foreach ($widgets['sidebar-1'] as $widget) {
      var_dump($wp_registered_widgets[$widget]); // dump the data
    }
    

    For more guidance, take a look at how dynamic_sidebar works, which is basically what I did to work out the above.

    Untested, but this was interesting enough that I mocked up some more complete code:

    global $wp_registered_widgets;
    $i = 1;
    $widgets = wp_get_sidebars_widgets(); 
    $widgets = $widgets['homepage-1'];
    if ( have_posts() ) { 
      while ( have_posts() ) { 
        the_post(); 
        if ($i%3 == 0){
          echo "<h1>WIDGET #".($i%3)."</h1>";
          $cn = $wp_registered_widgets[$widgets[$i%3]]['callback'][0];
          $cn = get_class($cn);
          the_widget($cn,$widgets[$i%3]);
        }
        get_template_part( 'content', get_post_format() );
        $i++;
      }
      _s_paging_nav(); 
    } else {
      get_template_part( 'content', 'none' ); 
    }
    
  2. You need to get it at the right time. I suggest on the wp action hook.

    For that, let’s steal some code from widgets.php, in the dynamic_sidebar function:

    add_action( 'wp', 'widgets_run' );
    function widgets_run() {
    
        global $wp_registered_widgets;
    
        $sidebars_widgets = wp_get_sidebars_widgets();
        if ( empty( $sidebars_widgets ) )
            return false;
    
        foreach ( (array) $sidebars_widgets as $sidebar_id => $sidebar_widgets ) {
    
            foreach( $sidebar_widgets as $sidebar_widget ) {
    
                if ( ! isset( $wp_registered_widgets[ $sidebar_widget ] ) )
                    continue;
    
                $classname_ = '';
                    foreach ( (array) $wp_registered_widgets[ $sidebar_widget ]['classname'] as $cn ) {
                    if ( is_string($cn) )
                        $classname_ .= '_' . $cn;
                    elseif ( is_object($cn) )
                        $classname_ .= '_' . get_class($cn);
                }
                $classnames[] = ltrim($classname_, '_');
    
            }
    
        }
    
        print_r($classnames); // here you are the class names
    
    }
    

Comments are closed.