Añadir clase a before_widget desde dentro de un widget personalizado
Tengo un widget personalizado simple que solicita su ancho (que se usa más tarde en el front-end). El campo de ancho es un menú desplegable, por lo que el usuario tiene opciones predefinidas.
Tendré muchas instancias de mi widget, cada una tendrá su propia configuración de ancho.
Ahora, en mi código de widget tengo el siguiente código:
echo $before_widget;
que resulta en:
<div class="widget my" id="my-widget-1"></div>
Lo que me gustaría hacer es de alguna manera conectarme a $before_widget
y añadir mi propia clase (el ancho especificado del menú desplegable). Por lo tanto, quiero obtener el siguiente marcado:
<div class="widget my col480" id="my-widget-3"></div>
Y si no hay ninguna clase especificada, entonces quiero añadir class="col480"
.
¿Cómo puedo lograr esto?
¡Gracias por la ayuda! Dasha

Ahá, entonces la variable $before_widget
es una cadena que representa un elemento div: <div class="widget my" id="my-widget-1">
. Así que verifiqué $before_widget
buscando la subcadena "class" y agregué mi valor $widget_width
a ella.
El código proviene de mi archivo de widget personalizado:
function widget( $args, $instance ) {
extract( $args );
... //otro código
$widget_width = !empty($instance['widget_width']) ? $instance['widget_width'] : "col300";
/* Agrega el ancho de $widget_width a la clase de $before_widget */
// si no existe atributo 'class' - agregar uno con el valor del ancho
if( strpos($before_widget, 'class') === false ) {
// incluir etiqueta de cierre en la cadena de reemplazo
$before_widget = str_replace('>', 'class="'. $widget_width . '">', $before_widget);
}
// si existe atributo 'class' - agregar el valor de ancho a él
else {
$before_widget = str_replace('class="', 'class="'. $widget_width . ' ', $before_widget);
}
/* Mostrar before_widget */
echo $before_widget;
... //otro código
}
Quería agregar mi variable $widget_width
al elemento div del widget dentro de mi propio código de widget (mientras tenía fácil acceso a la variable $widget_width
).
Espero que tenga sentido y ayude a alguien.
Gracias, Dasha

Puedes usar el gancho de filtro dynamic_sidebar_params
para encontrar tu widget y agregarle tus clases:
add_filter('dynamic_sidebar_params', 'add_classes_to__widget');
function add_classes_to__widget($params){
if ($params[0]['widget_id'] == "my-widget-1"){ //asegúrate de que sea el ID de tu widget aquí
// es tu widget, así que agregas tus clases
$classe_to_add = 'col480 whatever bla bla '; // asegúrate de dejar un espacio al final
$classe_to_add = 'class=" '.$classe_to_add;
$params[0]['before_widget'] = str_replace('class="',$classe_to_add,$params[0]['before_widget']);
}
return $params;
}

gracias por la respuesta. Tendré muchas instancias de mi widget personalizado, cada una con su propio ancho específico. Por eso quería agregar una clase adicional dentro del código del widget mismo, en lugar de hacerlo mediante un filtro. ¿Tiene sentido?

las opciones de instancia se guardan en la tabla de opciones, así que puedes obtenerlas desde ahí una vez que conozcas el ID del widget usando get_option('widget-name')

¡muchas gracias por tu ayuda! Lamento no entender realmente tu solución :( Y quería que todo el código estuviera dentro de mi archivo de widget personalizado, donde puedo acceder fácilmente a la variable de ancho. Terminé modificando la cadena $before_widget
. Tu respuesta me puso en el camino correcto al descubrir que $before_widget
es una cadena. Gracias de nuevo :)

Esta sería la opción preferida ya que utiliza filtros de WordPress en lugar de editar los archivos del tema

Otra forma que encontré para agregar una clase a un widget personalizado es usar la clave 'classname' en la función constructora como en:
class My_Widget_Class extends WP_Widget {
// En PHP anterior a 5 se usa el nombre de la clase hija para el constructor…
// function My_Widget_Class()
function __construct() {
$widget_ops = array(
'classname' => 'my-class-name',
'description' => __("Widget por el bien de la Humanidad",'themedomain'),
);
$control_ops = array(
'id_base' => 'my-widget-class-widget'
);
// más código después...
// Llama al constructor padre, puedes sustituir el 1er argumento por $control_ops['id_base'] y quitar el 4to.
parent::__construct(@func_get_arg(0),@func_get_arg(1),$widget_ops,$control_ops);
}
}
Y asegúrate de usar el 'before_widget' por defecto en tu tema o si usas register_sidebar()
en function.php, hazlo así:
// Esto es solo un ejemplo.
register_sidebar(array(
'name'=> 'Barra lateral',
'id' => 'sidebar-default',
'class' => '',// Nunca encontré dónde se usa esto...
'description' => 'Una barra lateral para la Humanidad',
'before_widget' => '<aside id="%1$s" class="widget %2$s">',// ¡Este es el código importante!
'after_widget' => '</aside>',
'before_title' => '<h3>',
'after_title' => '</h3>',
));
Entonces, en cada instancia de tu widget, tendrás la clase 'widget my-class-name' así:
<aside class="widget my-class-name" id="my-widget-class-widget-N"><!-- donde N es un número -->
<h3>TÍTULO DEL WIDGET</h3>
<p>CONTENIDO DEL WIDGET</p>
</aside>
También puedes llamar primero al constructor padre y luego añadir cualquier nombre de clase que desees:
class My_Widget_Class extends WP_Widget {
// Mejor definiendo la lista de argumentos del padre…
function __construct($id_base, $name, $widget_options = array(), $control_options = array())
{ parent::__construct($id_base, $name, $widget_options, $control_options);
// Cambia el nombre de la clase después
$this->widget_options['classname'].= ' alguna-extra';
}
}

primero añade una clase de marcador de posición personalizada en el constructor
<?php
public function __construct() {
$widget_ops = array(
'classname' =>; 'widget_text eaa __eaa__', //__eaa__ es mi clase css de marcador de posición
'description' =>; __( 'Anuncios de AdSense, texto arbitrario, HTML o JS.','eaa' ),
'customize_selective_refresh' =>; true,
);
$control_ops = array( 'width' =>; 400, 'height' =>; 350 );
parent::__construct( 'eaa', __( 'Easy AdSense Ads & Scripts', 'eaa' ), $widget_ops, $control_ops );
}
?>
Luego reemplázala con la(s) clase(s) de tu elección basado en las opciones del widget así
<?php
if ( $instance['no_padding'] ) {
$args['before_widget'] = str_replace( '__eaa__', 'eaa-clean', $args['before_widget'] );
}
?>
Puedes encontrar los detalles con un ejemplo en http://satishgandham.com/2017/03/adding-dynamic-classes-custom-wordpress-widgets/

Puedes probar este filtro:
/**
* Esta función recorre todos los widgets en la barra lateral
* y añade un valor del formulario de administración al widget como nombre de clase
*
* @param array $params Array de widgets en la barra lateral
* @return array
*/
add_filter( 'dynamic_sidebar_params', 'nen_lib_add_class_to_widget' );
function nen_lib_add_class_to_widget( $params )
{
foreach( $params as $key => $widget )
{
if( !isset($widget['widget_id']) ) continue;
// mi función personalizada para obtener datos del widget desde el formulario de administración (objeto)
$widget_data = nen_get_widget_data($widget['widget_id']) ;
// comprobar si el campo existe y tiene valor
if( isset($widget_data->wm_name) && $widget_data->wm_name )
{
// convertir y poner el valor en un array
$classes = array( sanitize_title( $widget_data->wm_name ) );
// añadir filtro, para poder agregar más
$classes = apply_filters( 'nen_lib_add_class_to_widget' , $classes , $widget['widget_id'] , $widget , $widget_data );
// obtener elemento 'before_widget', establecer buscar y reemplazar
$string = $params[$key]['before_widget'];
$find = '"widget ';
$replace = '"widget '.implode( ' ' , $classes ).' ';
// nuevo valor
$new_before = str_replace( $find , $replace , $string ) ;
// establecer nuevo valor
$params[$key]['before_widget'] = $new_before;
}
}
return $params;
}
