2

I have this code in a template file, which loads sidebar-sidebar_a.php:

get_sidebar('sidebar_a');

I would like to add a function to sidebar.php which has the effect of changing that to this if some condition is met:

get_sidebar('other');

so that it instead loads sidebar-other.php.

I thought that this would work, but it seems to have no effect:

add_action('get_sidebar', 'my_sidebar_logic');

function my_sidebar_logic($sidebar) {
    // Load a different sidebar if the user is logged in
    if (is_user_logged_in()) {
        return 'other';
    }

    return $sidebar;
}

What can I do to get the effect I want?

4 Answers 4

6

Get sidebar is a really thin wrapper around locate_template, which just searches the current child theme and parent theme directory for the given sidebar.

get_sidebar in wp-includes/general-template.php:

$templates = array();
if ( isset($name) )
    $templates[] = "sidebar-{$name}.php";

$templates[] = 'sidebar.php';

// Backward compat code will be removed in a future release
if ('' == locate_template($templates, true))
    load_template( ABSPATH . WPINC . '/theme-compat/sidebar.php');

}

And locate_template (in wp-includes/template.php):

<?php
/**
 * Retrieve the name of the highest priority template file that exists.
 *
 * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which
 * inherit from a parent theme can just overload one file.
 *
 * @since 2.7.0
 *
 * @param string|array $template_names Template file(s) to search for, in order.
 * @param bool $load If true the template file will be loaded if it is found.
 * @param bool $require_once Whether to require_once or require. Default true. Has no effect if $load is false.
 * @return string The template filename if one is located.
 */
function locate_template($template_names, $load = false, $require_once = true ) {
    $located = '';
    foreach ( (array) $template_names as $template_name ) {
        if ( !$template_name )
            continue;
        if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
            $located = STYLESHEETPATH . '/' . $template_name;
            break;
        } else if ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
            $located = TEMPLATEPATH . '/' . $template_name;
            break;
        }
    }

    if ( $load && '' != $located )
        load_template( $located, $require_once );

    return $located;
}

The reason your hook into get_sidebar doesn't work is because it's an action. It just fires. It doesn't allow you to change the result. Your sidebar will still be included regardless of the your hooked action.

That levels you a few options.

1. Pass a variable into get_sidebar

Chip Bennett's solution: pass a variable into the get_sidebar function. Not bad.

2. Write Your Own Sidebar Logic

And use it in place of get_sidebar. A simple example:

<?php
function mytheme_sidebar($name)
{
     $name = apply_filters('mytheme_sidebar', $name);
     get_sidebar($name);
}

Then use your own filter to modify the sidebar

<?php
add_filter('mytheme_sidebar', 'mytheme_custom_sidebar');
function mytheme_custom_sidebar($name)
{
    return is_user_logged_in() ? 'loggedin' : $name;
}

This will be the most flexible. If it's a public theme, end users will be able to customize things. If it's for a client, when the inevitably ask you for more stuff, it's easily done.

3. Look Deeper

get_sidebar just includes the appropriate theme files. dynamic_sidebar is where the work is done.

If you take a look inside that function, the most interesting line is:

$sidebars_widgets = wp_get_sidebars_widgets();

wp_get_sidebars_widgets fetches all the currently registered widgets for all sidebars on the site.

<?php
/**
 * Retrieve full list of sidebars and their widgets.
 *
 * Will upgrade sidebar widget list, if needed. Will also save updated list, if
 * needed.
 *
 * @since 2.2.0
 * @access private
 *
 * @param bool $deprecated Not used (deprecated).
 * @return array Upgraded list of widgets to version 3 array format when called from the admin.
 */
function wp_get_sidebars_widgets($deprecated = true) {
    if ( $deprecated !== true )
        _deprecated_argument( __FUNCTION__, '2.8.1' );

    global $wp_registered_widgets, $_wp_sidebars_widgets, $sidebars_widgets;

    // If loading from front page, consult $_wp_sidebars_widgets rather than options
    // to see if wp_convert_widget_settings() has made manipulations in memory.
    if ( !is_admin() ) {
        if ( empty($_wp_sidebars_widgets) )
            $_wp_sidebars_widgets = get_option('sidebars_widgets', array());

        $sidebars_widgets = $_wp_sidebars_widgets;
    } else {
        $sidebars_widgets = get_option('sidebars_widgets', array());
    }

    if ( is_array( $sidebars_widgets ) && isset($sidebars_widgets['array_version']) )
        unset($sidebars_widgets['array_version']);

    $sidebars_widgets = apply_filters('sidebars_widgets', $sidebars_widgets);
    return $sidebars_widgets;
}

The key line there: apply_filters('sidebars_widget', ...). Money.

Register a secondary sidebar only for logged in users:

<?php
add_action('widgets_init', 'wpse64492_register');
function wpse64492_register()
{
    register_sidebar(array(
        'name'  => __('Logged In Sidebar', 'wpse64492'),
        'id'    => 'logged-in'
    ));
}

Then hook into sidebars_widgets and swap the normal sidebar for the logged in version.

<?php
add_filter('sidebars_widgets', 'wpse64492_switch');
function wpse64492_switch($widgets)
{
    if(is_admin())
        return $widgets;

    $key = 'sidebar-1'; // the sidebar you want to change!

    if(isset($widgets[$key]) && is_user_logged_in() && isset($widgets['logged-in']))
        $widgets[$key] = $widgets['logged-in'];

    return $widgets;
}
0
3

Just pass a variable to get_sidebar():

// Determine sidebar
$sidebar = ( is_user_logged_in() ? 'other' : 'sidebar_a' );
// Get the sidebar
get_sidebar( $sidebar );
1

Themes

Just wrap it in the thinnest and most unintrusive logic: A filter.

// In you theme: Calls the default sidebar
get_sidebar( apply_filters( 'wpse64492_sidebar', '' ) );

Then you can switch in your functions.php file:

function wpse64492_sidebar_name( $name = '' )
{
    // Call sidebar-single.php on single view posts
    is_single() AND $name = 'single';

    return $name;
}
add_filter( 'wpse64492_sidebar', 'wpse64492_sidebar_name' );

Plugins

If you want to do it from a plugin, use the action:

<?php
/** Plugin Name: (#64492) Switch sidebars per request */
function wpse64492_sidebar( $name )
{
    // Conditional logic: Some other sidebar for page 2+ on paged archives
    if ( is_paged() )
    {
        // Avoid recurrsion: remove itself
        remove_filter( current_filter(), __FUNCTION__ );
        return get_sidebar( 'paged' );
    }

    // Default return
    return $name;
}
add_action( 'get_sidebar', 'wpse64492_sidebar' );
0

You can call the actual sidebar in the function as well.

add_action('get_sidebar', 'my_sidebar_logic');

function my_sidebar_logic($sidebar) {
    // Load a different sidebar if the user is logged in
    if (is_user_logged_in()) {
          get_sidebar('other');
    }   
}
2
  • This doesn't result in a recursive loop? Commented Sep 7, 2012 at 16:54
  • Ah you're probably right, I didn't fully comprehend the question, I was thinking about dynamic sidebar
    – Wyck
    Commented Sep 7, 2012 at 17:06

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.