7

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.

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; ?>

2 Answers 2

3

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' ); 
}
3
  • @furins : see the update
    – s_ha_dum
    Commented Jan 5, 2014 at 17:03
  • Looking at dynamic_sidebar code should be the most obvious approach to follow and I've not thought of it! Now I feel silly. +1 also for (correctly) reducing my question to a single sentence. The code has some small errors on it but they are trivial and they do not change the correctness of the answer since they only output the wrong widget (it should be $widgets[$i/3]). Thank you!
    – furins
    Commented Jan 5, 2014 at 22:15
  • I must have misunderstood which widgets were supposed to show where. Sorry about that. Glad it helped though.
    – s_ha_dum
    Commented Jan 5, 2014 at 22:25
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

}
2
  • The code is robust because it checks variables before using them, I'm going to steal part of it in order to merge with s_ha_dum's answer. At the very end both the approaches presented are correct but s_ha_dum's one is more focused on my question and thus more easily applicable to my specific problem. However thank you very much, if I could only accept both...
    – furins
    Commented Jan 5, 2014 at 22:20
  • That's fine, @furins. We're here to help each other. And by checking variables we end up seeing only the relevant warning messages. Commented Jan 6, 2014 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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