Crear múltiples sidebars usando nuestros menús de WordPress

Los sidebars son las columnas de WordPress en las cuales podemos organizar y mostrar nuestros widgets. Para crear nuevos sidebars, estos deben registrarse como variables en el entorno, de este modo:

$sidebar_name = 'Sidebar 1';
register_sidebar(array(
	'name' => $sidebar_name,
	'before_widget' => '<div id="%1$s" class="%2$s">',
	'after_widget' => '</div>',
	'before_title' => '<h3>',
	'after_title' => '</h3>',
));

O también registrando varios a la vez:

register_sidebars(3, array('name'=>'Sidebar %d'));

Si necesitas crear nuevas columnas para cada sección de tu sitio, puedes hacerlo dinámicamente utilizando los ítems declarados en el menú. Por ejemplo, tenemos creado un menú llamado “Navigation” en el que están todas las secciones de nuestro sitio web:

Entonces, podemos traer los ítems de este menú y crear los sidebars que necesitamos:

// functions.php
$menu_name = "Navigation";
$navigation_items = wp_get_nav_menu_items($menu_name);
if(!empty($navigation_items)){
	// sort
	foreach($navigation_items as $item){
		$sidebar_name = $item->title;
		register_sidebar(array(
			'name' => $sidebar_name,
			'before_widget' => '<div id="%1$s" class="%2$s">',
			'after_widget' => '</div>',
			'before_title' => '<h3>',
			'after_title' => '</h3>',
		));
	}
}

Lo que genera un sidebar para cada ítem del menú escogido:

Algo que siempre debes tener en cuenta al trabajar con sidebars, es que no existe una relación directa entre estos y sus widgets, sino que se relacionan por el orden en que fueron registrados. Por ejemplo: si un widget esta incluído en el segundo sidebar, y luego se registra otra columna antes que este, entonces el widget quedará incluído en el segundo sidebar, aunque no sea el mismo en el que fue colocado. En este caso, si cambiamos el orden de los ítems en el menú principal, esto puede cambiar la posición de los widgets respecto de las columnas. Un modo de resolverlo es ordenar por ID los items obtenidos del menú, antes de hacer el registro.

$menu_name = "Navigation";
$navigation_items = wp_get_nav_menu_items($menu_name);
if(!empty($navigation_items)){
	$order_items = array();
	foreach ($navigation_items as $key => $row){
		$order_items[$key] = $row->ID;
	}
	array_multisort($order_items, SORT_DESC, $navigation_items);
	foreach($navigation_items as $item){
		// Comenzar registro de cada sidebar
	}
}

Por último, para aplicar este distingo en nuestra web, necesitamos condicionar los sidebars para mostrar sólo el que corresponda dependiendo de la sección en la que nos encontremos:

// sidebar.php
if ( function_exists("dynamic_sidebar") ) {
	$menu_name = "Navigation";
	$navigation_items = wp_get_nav_menu_items($menu_name);
	if(!empty($navigation_items)){
		global $post;
		foreach($navigation_items as $item){
			// Si es página actual o página inferior
			if( $item->object == 'page' && ( is_page($item->object_id) || in_array( $item->object_id, get_post_ancestors($post) ) ) ):
				dynamic_sidebar($item->title);
			// Si es categoría o entrada de una categoría
			elseif( $item->object == 'category' && ( is_category( $item->object_id ) || ( is_single() && in_category( $item->object_id, $post->ID ) ) ) ):
				dynamic_sidebar($item->title);
			// Si es custom item
			elseif( $item->object == 'custom' && strpos( $item->url, $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] ) ):
				dynamic_sidebar($item->title);
			endif;
		}
	}
}

9 thoughts on “Crear múltiples sidebars usando nuestros menús de WordPress”

  1. ¡Hola!
    Genial tu post. ¡Muchas gracias!
    Me surge una duda:
    ¿Cómo distingo entre la sección padre y el hijo? No quiero que una sección perteneciente a otra tenga sume el sidebar del padre con el del hijo. ¿Es posible?
    ¡Gracias!

    1. Hola Ana, creo que siempre en este tipo de casos la solución dependerá de lo específico o generalizado del comportamiento que necesitas reproducir. Una solución podría ser separar las condiciones entre la página superior y las páginas inferiores:

      // Página Superior
      // if ( $item->object == ‘page’ && is_page($item->object_id) )
      // Páginas Inferiores
      // if ( $item->object == ‘page’ && in_array( $item->object_id, get_post_ancestors($post) ) )

      Otro enfoque es condicionar los widgets del sidebar, dependiendo de la data obtenida en $post.
      Saludos!

  2. Hola, tengo una duda: si quisiera cambiar la frase de “buscar por” por “ingrese el texto” el el widget buscar ¿desde dónde lo hago?, porque con el Firebug puedo ver la línea donde está la frase “buscar por” pero no sé en que archivo está para editarla y cambiarla.
    Gracias

    1. Hola Fabián,
      Ese texto es una variable traducible de WordPress, que se encuentra en el widget predeterminado del core, y debe ser algo similar a _e(“Search for:”). El texto que mencionas, proviene de la traducción hecha desde el inglés. Para cambiarlo, lo correcto es modificar el catálogo de traducciones .po, ubicado en la carpeta /wp-content/languages. Probablemente uses algo similar a es_ES.po o es_AR.po. Para abrir el archivo, debes utilizar el programa poedit. Una vez abierto el archivo, buscas la cadena de texto “buscar por”, y editarla por el texto que deseas. Po último, modificas las cabeceras del archivo en Catálogo > Opciones, y reemplazas los archivos .PO y .MO generados.

      La otra opción, menos recomendada pero igual de efectiva, es cambiar el texto por javascript.

      Por último, recuerda no intervenir por ningún motivo el texto directamente en el widget ubicado en wp-includes, ya que esos archivos luego son cambiados en las actualizaciones, por lo que el cambio no sería sostenible en el tiempo.

      Saludos,
      Basilio

  3. Hice todo lo que indicas y todo esta bien hasta la parte de widgets, en el administrador veo todo el listado y no hay errores, el problema es que cuando pongo un widget en un Item no aparece en el sidebar.
    Me podrías ayudar.

    1. Hola Pedro,
      Probé el código en la versión 3.6 de WP y sigue funcionando. Te recomiendo lo siguiente:

      Revisa que tengas asignado el menú creado como navegación principal, si usas algún theme como Twenty Thirteen u otro que posea Locations
      Revisa que el nombre de la variable $menu_name corresponda al menú que usarás para generar los sidebars.
      Revisa que las condiciones para detectar el sidebar activo correspondan al tipo de objeto en el que estas (página normal, categoría, custom post_type, etc)

      Saludos,
      @basilio

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>