Agregar widgets mediante programación a las barras laterales

60

Me gustaría agregar widgets mediante programación a mis dos barras laterales que tengo. ¿No pude encontrar ninguna forma oficial de hacerlo?

Comencé a buscar en la base de datos. Descubrí que es la opción 'sidebars_widgets' que coloca los widgets en las barras laterales. Al mirar las opciones, los nombres de los widgets tienen un número agregado al final como: widget_name-6. ¿De dónde viene ese número?

¿Alguna idea sobre cómo solucionar este problema?

    
pregunta Marlun 22.08.2011 - 13:45

4 respuestas

86

Cuando comencé esta respuesta, debería ser solo una pequeña nota. Bueno, fallé. ¡Lo siento! Quédate conmigo, hay un regalo escondido en el fondo ...

Cómo se almacenan los widgets de WordPress

La lista de widgets se almacena en una opción llamada 'sidebars_widgets' . Un var_export() puede dar algo como lo siguiente:

array (
  'wp_inactive_widgets' => 
  array (
  ),
  'top-widget' => 
  array (
  ),
  'bottom-widget' => 
  array (
  ),
  'array_version' => 3,
)

Ignora 'wp_inactive_widgets' y 'array_version' . No tenemos que preocuparnos por eso.
Las otras claves son identificador para barras laterales registradas. En este caso, las barras laterales pueden haberse registrado con este código:

// Register two sidebars.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
    register_sidebar(
        array (
            'name'          => $sidebar,
            'id'            => $sidebar,
            'before_widget' => '',
            'after_widget'  => ''
        )
    );
}

Por defecto, las barras laterales están vacías después del registro. Por supuesto.

Para cada clase de widget registrada se crea una opción separada, que contiene todas las opciones necesarias. La opción está prefijada por la cadena widget_ . Para obtener las opciones para todos los widgets RSS activos, tenemos que examinar ...

get_option( 'widget_rss' );

Salida posible:

array (
  2 => 
  array (
    'title' => 'WordPress Stack Exchange',
    'url' => 'http://wordpress.stackexchange.com/feeds',
    'link' => 'http://wordpress.stackexchange.com/questions',
    'items' => 5,
    'show_summary' => 1,
    'show_author' => 0,
    'show_date' => 0,
  ),
)

Anote el número 2 . Los argumentos para múltiples instancias se almacenan en esta opción ordenada por números.

Para ver qué clases de widgets ya se conocen en WordPress, vaya a wp-admin/options.php y desplácese hacia abajo hasta que vea algo como esto:

Sí,datosserializados.No,nopuedesleerlosaquí.Notepreocupes,notienesquehacerlo.

Unwidgetdedemostración

Parailustrarmejorelfuncionamientointerno,heescritounwidgetdedemostraciónmuysimple:

/***Supersimplewidget.*/classT5_Demo_WidgetextendsWP_Widget{publicfunction__construct(){//id_base,visiblenameparent::__construct('t5_demo_widget','T5DemoWidget');}publicfunctionwidget($args,$instance){echo$args['before_widget'],wpautop($instance['text']),$args['after_widget'];}publicfunctionform($instance){$text=isset($instance['text'])?esc_textarea($instance['text']):'';printf('<textareaclass="widefat" rows="7" cols="20" id="%1$s" name="%2$s">%3$s</textarea>',
            $this->get_field_id( 'text' ),
            $this->get_field_name( 'text' ),
            $text
        );
    }
}

Tenga en cuenta que el constructor: 't5_demo_widget' es el $id_base , el identificador de este widget. Como puede ver en la captura de pantalla, sus argumentos se almacenan en la opción widget_t5_demo_widget . Todos tus widgets personalizados serán tratados así. No tienes que adivinar el nombre. Y como usted ha escrito sus widgets (probablemente) conoce todos los argumentos de los parámetros ' $instance de su clase'.

Elementos básicos del tema

Primero tienes que registrar algunas barras laterales y el widget personalizado. La acción correcta para esto es fácil de recordar: 'widgets_init' . Pon todo en un contenedor, una clase o una función. Para simplificar, usaré una función llamada t5_default_widget_demo() .

Todo el siguiente código entra en el functions.php . La clase T5_Demo_Widget ya debería estar cargada. Acabo de ponerlo en el mismo archivo ...

add_action( 'widgets_init', 't5_default_widget_demo' );

function t5_default_widget_demo()
{
    // Register our own widget.
    register_widget( 'T5_Demo_Widget' );

    // Register two sidebars.
    $sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
    foreach ( $sidebars as $sidebar )
    {
        register_sidebar(
            array (
                'name'          => $sidebar,
                'id'            => $sidebar,
                'before_widget' => '',
                'after_widget'  => ''
            )
        );
    }

Hasta ahora, tan simple. Nuestro tema ahora está listo para el widget, el widget de demostración es conocido. Ahora la diversión.

$active_widgets = get_option( 'sidebars_widgets' );

if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
    or ! empty ( $active_widgets[ $sidebars['b'] ] )
)
{   // Okay, no fun anymore. There is already some content.
    return;
}

Realmente no quieres destruir la configuración del usuario. Si ya hay algo de contenido en las barras laterales, su código no debería ejecutarse sobre él. Por eso nos detenemos en este caso.

Bien, asumimos que las barras laterales están vacías ... necesitamos un contador:

$counter = 1;

Los widgets están numerados . Estos números son segundos identificadores para WordPress.

Hagamos que la matriz lo cambie:

$active_widgets = get_option( 'sidebars_widgets' );

También necesitamos un contador (más sobre esto más adelante):

$counter = 1;

Y aquí es cómo usamos el contador, los nombres de la barra lateral y los argumentos del widget (bueno, tenemos un solo argumento: text ).

// Add a 'demo' widget to the top sidebar …
$active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
// … and write some text into it:
$demo_widget_content[ $counter ] = array ( 'text' => "This works!\n\nAmazing!" );

$counter++;

Observe cómo se crea el identificador del widget: el id_base , un menos - y el contador. El contenido del widget se almacena en otra variable $demo_widget_content . Aquí está el contador, la tecla y los argumentos del widget se almacenan en una matriz.

Incrementamos el contador en uno cuando terminamos para evitar colisiones.

Eso fue fácil. Ahora un widget de RSS. ¡Más campos, más diversión!

$active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
// The latest 15 questions from WordPress Stack Exchange.
$rss_content[ $counter ] = array (
    'title'        => 'WordPress Stack Exchange',
    'url'          => 'http://wordpress.stackexchange.com/feeds',
    'link'         => 'http://wordpress.stackexchange.com/questions',
    'items'        => 15,
    'show_summary' => 0,
    'show_author'  => 1,
    'show_date'    => 1,
);
update_option( 'widget_rss', $rss_content );

$counter++;

Aquí hay algo nuevo: update_option() esto almacenará el argumento del widget RSS en una opción separada. WordPress los encontrará automáticamente más tarde.
No guardamos los argumentos del widget de demostración porque ahora agregamos una segunda instancia a nuestra segunda barra lateral ...

// Okay, now to our second sidebar. We make it short.
$active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
#$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
$demo_widget_content[ $counter ] = array ( 'text' => 'The second instance of our amazing demo widget.' );
update_option( 'widget_t5_demo_widget', $demo_widget_content );

... y guarda todos los argumentos para el t5_demo_widget de una vez. No es necesario actualizar la misma opción dos veces.

Bueno, suficientes widgets para hoy, también guardemos sidebars_widgets :

update_option( 'sidebars_widgets', $active_widgets );

Ahora, WordPress sabrá que hay algunos widgets registrados y dónde se almacenan los argumentos para cada widget. Un var_export() en el sidebar_widgets se verá así:

array (
  'wp_inactive_widgets' => 
  array (
  ),
  'top-widget' => 
  array (
    0 => 't5_demo_widget-1',
    1 => 'rss-2',
  ),
  'bottom-widget' => 
  array (
    0 => 't5_demo_widget-3',
  ),
  'array_version' => 3,
)

El completo < a href="https://github.com/toscho/T5-Default-Widget-Demo" title="Realmente espero que Chip Bennett nunca vea esto. Violé todos los requisitos de temas conocidos."> código de nuevo :

add_action( 'widgets_init', 't5_default_widget_demo' );

function t5_default_widget_demo()
{
    // Register our own widget.
    register_widget( 'T5_Demo_Widget' );

    // Register two sidebars.
    $sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
    foreach ( $sidebars as $sidebar )
    {
        register_sidebar(
            array (
                'name'          => $sidebar,
                'id'            => $sidebar,
                'before_widget' => '',
                'after_widget'  => ''
            )
        );
    }

    // Okay, now the funny part.

    // We don't want to undo user changes, so we look for changes first.
    $active_widgets = get_option( 'sidebars_widgets' );

    if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
        or ! empty ( $active_widgets[ $sidebars['b'] ] )
    )
    {   // Okay, no fun anymore. There is already some content.
        return;
    }

    // The sidebars are empty, let's put something into them.
    // How about a RSS widget and two instances of our demo widget?

    // Note that widgets are numbered. We need a counter:
    $counter = 1;

    // Add a 'demo' widget to the top sidebar …
    $active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
    // … and write some text into it:
    $demo_widget_content[ $counter ] = array ( 'text' => "This works!\n\nAmazing!" );
    #update_option( 'widget_t5_demo_widget', $demo_widget_content );

    $counter++;

    // That was easy. Now a RSS widget. More fields, more fun!
    $active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
    // The latest 15 questions from WordPress Stack Exchange.
    $rss_content[ $counter ] = array (
        'title'        => 'WordPress Stack Exchange',
        'url'          => 'http://wordpress.stackexchange.com/feeds',
        'link'         => 'http://wordpress.stackexchange.com/questions',
        'items'        => 15,
        'show_summary' => 0,
        'show_author'  => 1,
        'show_date'    => 1,
    );
    update_option( 'widget_rss', $rss_content );

    $counter++;

    // Okay, now to our second sidebar. We make it short.
    $active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
    #$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
    $demo_widget_content[ $counter ] = array ( 'text' => 'The second instance of our amazing demo widget.' );
    update_option( 'widget_t5_demo_widget', $demo_widget_content );

    // Now save the $active_widgets array.
    update_option( 'sidebars_widgets', $active_widgets );
}

Si vas a wp-admin/widgets.php ahora verás tres widgets preestablecidos:

Y eso es todo. Utilizar ...

dynamic_sidebar( 'top-widget' );
dynamic_sidebar( 'bottom-widget' );

... para imprimir los widgets.

Hay una pequeña falla: debe cargar el extremo frontal dos veces para el registro inicial. Si alguien puede ayudar, estaré muy agradecido.

    
respondido por el fuxia 04.05.2012 - 04:23
3

Gracias por compartir tu solución. He usado lo que se ha descrito en esta pregunta para crear un fragmento de código que se puede usar para inicializar barras laterales con mucha facilidad. Es muy flexible, puede crear tantos widgets como desee sin tener que modificar el código en absoluto. Solo haga uso de los ganchos de filtro y pase los argumentos en una matriz. Aquí está el código comentado:

function initialize_sidebars(){

  $sidebars = array();
  // Supply the sidebars you want to initialize in a filter
  $sidebars = apply_filters( 'alter_initialization_sidebars', $sidebars );

  $active_widgets = get_option('sidebars_widgets');

  $args = array(
    'sidebars' => $sidebars,
    'active_widgets' => $active_widgets,
    'update_widget_content' => array(),
  );

  foreach ( $sidebars as $current_sidebar_short_name => $current_sidebar_id ) {

    $args['current_sidebar_short_name'] = $current_sidebar_short_name;
    // we are passing our arguments as a reference, so we can modify their contents
    do_action( 'your_plugin_sidebar_init', array( &$args ) );

  }
  // we only need to update sidebars, if the sidebars are not initialized yet
  // and we also have data to initialize the sidebars with
  if ( ! empty( $args['update_widget_content'] ) ) {

    foreach ( $args['update_widget_content'] as $widget => $widget_occurence ) {

      // the update_widget_content array stores all widget instances of each widget
      update_option( 'widget_' . $widget, $args['update_widget_content'][ $widget ] );

    }
    // after we have updated all the widgets, we update the active_widgets array
    update_option( 'sidebars_widgets', $args['active_widgets'] );

  }

}

Esta es una función auxiliar que verifica si la barra lateral ya tiene contenido:

function check_sidebar_content( $active_widgets, $sidebars, $sidebar_name ) {

  $sidebar_contents = $active_widgets[ $sidebars[ $sidebar_name ] ];

  if ( ! empty( $sidebar_contents ) ) {

    return $sidebar_contents;

  }

  return false;

}

Ahora necesitamos crear una función que esté enganchada a la acción 'sidebar_init'.

add_action( 'your_plugin_sidebar_init', 'add_widgets_to_sidebar' );

function add_widgets_to_sidebar( $args ) {

  extract( $args[0] );

  // We check if the current sidebar already has content and if it does we exit
  $sidebar_element = check_sidebar_content( $active_widgets, $sidebars, $current_sidebar_short_name );

  if ( $sidebar_element !== false  ) {

    return;

  }

  do_action( 'your_plugin_widget_init', array( &$args ) );

}

Y ahora la inicialización del widget:

add_action( 'your_plugin_widget_init', 'your_plugin_initialize_widgets' );

function your_plugin_initialize_widgets( $args ) {

  extract( $args[0][0] );

  $widgets = array();

  // Here the widgets previously defined in filter functions are initialized,
  // but only those corresponding to the current sidebar 
  $widgets = apply_filters( 'alter_initialization_widgets_' . $current_sidebar_short_name, $widgets );

  if ( ! empty( $widgets ) ) {

    do_action( 'create_widgets_for_sidebar', array( &$args ), $widgets );

  }

}

La última acción es crear los widgets en cada barra lateral:

add_action( 'create_widgets_for_sidebar', 'your_plugin_create_widgets', 10, 2 );

function your_plugin_create_widgets( $args, $widgets ) {

  extract( $args[0][0][0] );

  foreach ( $widgets as $widget => $widget_content ) {

    // The counter is increased on a widget basis. For instance, if you had three widgets,
    // two of them being the archives widget and one of the being a custom widget, then the
    // correct counter appended to each one of them would be archive-1, archive-2 and custom-1.
    // So the widget counter is not a global counter but one which counts the instances (the
    // widget_occurrence as I have called it) of each widget.
    $counter = count_widget_occurence( $widget, $args[0][0][0]['update_widget_content'] );

    // We add each instance to the active widgets...
    $args[0][0][0]['active_widgets'][ $sidebars[ $current_sidebar_short_name ] ][] = $widget . '-' . $counter;

    // ...and also save the content in another associative array.
    $args[0][0][0]['update_widget_content'][ $widget ][ $counter ] = $widget_content;

  }

}

Esta función se utiliza para realizar un seguimiento de cuántas instancias de un widget específico ya se han definido:

function count_widget_occurence( $widget, $update_widget_content ) {

  $widget_occurrence = 0;

  // We look at the update_widget_content array which stores each
  // instance of the current widget with the current counter in an 
  // associative array. The key of this array is the name of the 
  // current widget.
      // Having three archives widgets for instance would look like this:
      // 'update_widget_content'['archives'] => [1][2][3] 
  if ( array_key_exists( $widget, $update_widget_content ) ) {

    $widget_counters = array_keys( $update_widget_content[ $widget ] );

    $widget_occurrence = end( $widget_counters );

  }

  $widget_occurrence++;

  return $widget_occurrence;

}

Lo último que debemos hacer es asignar valores. Hacer uso de estas funciones de filtro:

add_filter( 'alter_initialization_sidebars', 'current_initialization_sidebars' ) ;
// Use this filter hook to specify which sidebars you want to initialize
function current_initialization_sidebars( $sidebars ) {

  // The sidebars are assigned in this manner.
  // The array key is very important because it is used as a suffix in the initialization function
  // for each sidebar. The value is what is used in the html attributes.
  $sidebars['info'] = 'info-sidebar';

  return $sidebars;

}

Y:

add_filter( 'alter_initialization_widgets_info', 'current_info_widgets' );
// Add a filter hook for each sidebar you have. The hook name is derived from
// the array keys passed in the alter_initialization_sidebars filter. 
// Each filter has a name of 'alter_initialization_widgets_' and the array 
// key appended to it.

function current_info_widgets( $widgets ) {
  // This filter function is used to add widgets to the info sidebar. Add each widget
  // you want to assign to this sidebar to an array.

  return $widgets = array(
    // Use the name of the widget as specified in the call to the WP_Widget constructor
    // as the array key.

    // The archives widget is a widget which is shipped with wordpress by default.
    // The arguments used by this widget, as all other default widgets, can be found
    // in wp-includes/default-widgets.php. 

    'archives' => array(
      // Pass in the array options as an array
      'title' => 'Old Content',
      'dropdown' => 'on',
      // The 'on' value is arbitrarily chosen, the widget actually only checks for
      // a non-empty value on both of these options
      'count' => 'on',
    ),
 );

}

Lo ideal sería llamar a initialize_sidebars en una función de configuración que se llama en el complemento o la activación del tema de esta manera: Activación del tema:

add_action( 'after_switch_theme', 'my_activation_function' );
function my_activation_function() {
  initialize_sidebars();
}

Activación del complemento:

register_activation_hook( __FILE__, 'my_activation_function' );
function my_activation_function() {
  initialize_sidebars();
}

Para resumir el uso de este conglomerado de funciones:

  1. crea una función que inicializa las barras laterales que se engancha al filtro 'alter_initialization_sidebars'.

  2. cree una función para cada barra lateral que acaba de agregar que está enganchada al filtro 'alter_initialization_widgets_ $ sidebarname'. Reemplace $ sidebarname con el nombre de cada barra lateral que creó en el paso 1.

También puede simplemente copiar este código sin comentarios en su archivo de funciones y comenzar a crear sus funciones de filtro de inmediato: Código en pastie (sin funciones de filtro de inicialización)

    
respondido por el BdN3504 12.10.2014 - 14:25
2

En primer lugar, gracias a @toscho por la respuesta detallada.

Este es un ejemplo simple para aquellos que buscan una solución simple y opciones de widget predeterminadas:

$active_sidebars = get_option( 'sidebars_widgets' ); //get all sidebars and widgets
$widget_options = get_option( 'widget_name-1' );
$widget_options[1] = array( 'option1' => 'value', 'option2' => 'value2' );

if(isset($active_sidebars['sidebar-id']) && empty($active_sidebars['sidebar-id'])) { //check if sidebar exists and it is empty

    $active_sidebars['sidebar-id'] = array('widget_name-1'); //add a widget to sidebar
    update_option('widget_name-1', $widget_options); //update widget default options
    update_option('sidebars_widgets', $active_sidebars); //update sidebars
}

Nota 1: Puedes obtener sidebar-id yendo al menú de widgets e inspeccionando la barra lateral deseada. El primer <div id="widgets-holder-wrap"> 's <div> child tiene el sidebar-id .

Nota 2: Puede obtener widget_name yendo al menú de widgets e inspeccionando el widget deseado. Verás algo como <div id="widget-6_widget_name-__i__" class="widget ui-draggable"> .

Me gustaría que ayude.

    
respondido por el Manolo 19.08.2014 - 10:59
0

Así es como lo haces:

(ADVERTENCIA, esto podría QUITAR todos los widgets anteriores si no volviste a colocar los widgets originales en la matriz widgets ).

    $widgets = array(
    'middle-sidebar' => array(
        'widget_name'
    ),
    'right-sidebar' => array(
        'widget2_name-1'
    )
);
update_option('sidebars_widgets', $widgets);

El número puede usarse si más adelante quieres agregar opciones al widget con algo como esto:

    update_option('widget_widget_name', array(
    1 => array(
        'title' => 'The tile',
        'number' => 4
    ),
    '_multiwidget' => 1
));
    
respondido por el its_me 10.03.2017 - 06:25

Lea otras preguntas en las etiquetas