Ajouter par programme des widgets aux barres latérales

62

Je voudrais ajouter par programme des widgets à mes deux barres latérales que j'ai. Je n'ai pas trouvé de moyen officiel de le faire?

J'ai commencé à chercher dans la base de données. J'ai constaté que c'est l'option 'sidebars_widgets' qui place les widgets dans les barres latérales. Lorsque vous examinez les options, un nom est ajouté à la fin du nom du widget, par exemple: nom_du_green-6. D'où vient ce nombre?

Une idée pour savoir comment régler ça?

Marlun
la source
6
Vous devriez ajouter votre réponse ci-dessous pour répondre à votre propre question :)
helenhousandi
Pour un aperçu complet des widgets de la barre latérale, consultez cet article: justintadlock.com/archives/2010/11/08/sidebars-in-wordpress .
Josué
Surveillez le paramètre d'action de l'appel ajax effectué lorsqu'un widget est ajouté, puis recherchez le code associé à cette action ajax hook et voyez comment il est exécuté dans le noyau. Facile! ;)
Ashfame
5
Veuillez republier votre solution en tant que réponse et acceptez-la comme "la" réponse à votre problème.
EAMann

Réponses:

91

Quand j'ai commencé cette réponse, cela ne devrait être qu'une petite note. Eh bien, j'ai échoué. Pardon! Reste avec moi, il y a un goody caché au fond…

Comment les widgets WordPress sont stockés

La liste des widgets est stockée dans une option nommée 'sidebars_widgets'. A var_export()peut donner quelque chose comme ce qui suit:

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

Ignorer 'wp_inactive_widgets'et 'array_version'. Nous n'avons pas à nous soucier de ceux-ci.
Les autres clés sont l'identifiant des barres latérales enregistrées. Dans ce cas, les barres latérales peuvent avoir été enregistrées avec ce code:

// 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'  => ''
        )
    );
}

Par défaut, les barres latérales sont vides après l'enregistrement. Bien sûr.

Pour chaque classe de widget enregistrée, une option distincte est créée, contenant toutes les options nécessaires. L'option est préfixée par la chaîne widget_. Pour obtenir les options pour tous les widgets RSS actifs, nous devons examiner…

get_option( 'widget_rss' );

Sortie possible:

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,
  ),
)

Notez le nombre 2 . Les arguments de plusieurs instances sont tous stockés dans cette seule option triée par nombre.

Pour voir quelles classes de widgets sont déjà connues de WordPress, allez à wp-admin/options.phpet faites défiler l'écran jusqu'à ce que vous voyiez quelque chose comme ceci:

capture d'écran des options de widgets sérialisés

Oui, données sérialisées. Non, vous ne pouvez pas les lire ici. Ne t'inquiète pas, tu n'es pas obligé.

Un widget de démonstration

Pour mieux illustrer le fonctionnement interne, j'ai écrit un widget de démonstration très simple:

/**
 * Super simple widget.
 */
class T5_Demo_Widget extends WP_Widget
{
    public function __construct()
    {                      // id_base        ,  visible name
        parent::__construct( 't5_demo_widget', 'T5 Demo Widget' );
    }

    public function widget( $args, $instance )
    {
        echo $args['before_widget'], wpautop( $instance['text'] ), $args['after_widget'];
    }

    public function form( $instance )
    {
        $text = isset ( $instance['text'] )
            ? esc_textarea( $instance['text'] ) : '';
        printf(
            '<textarea class="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
        );
    }
}

Notez le constructeur: 't5_demo_widget'est $id_basel'identifiant de ce widget. Comme vous pouvez le voir sur la capture d'écran, ses arguments sont stockés dans l'option widget_t5_demo_widget. Tous vos widgets personnalisés seront traités comme ceci. Vous n'avez pas à deviner le nom. Et puisque vous avez écrit (probablement) vos widgets, vous connaissez tous les arguments des $instanceparamètres de votre classe .

Bases de thème

Vous devez d’abord enregistrer des barres latérales et le widget personnalisé. L'action appropriée pour cela est facile à retenir: 'widgets_init'. Mettez tout dans un conteneur - une classe ou une fonction. Pour plus de simplicité, je vais utiliser une fonction nommée t5_default_widget_demo().

Tout le code suivant va dans le functions.php. La classe T5_Demo_Widgetdevrait déjà être chargée. Je viens de le mettre dans le même fichier…

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'  => ''
            )
        );
    }

Jusqu'ici, si simple. Notre thème est maintenant prêt pour le widget, le widget de démonstration est connu. Maintenant l'amusement.

$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;
}

Vous ne voulez vraiment pas détruire les paramètres utilisateur. S'il y a déjà du contenu dans les barres latérales, votre code ne devrait pas l'exécuter. C'est pourquoi nous nous arrêtons dans ce cas.

OK, supposons que les barres latérales sont vides… nous avons besoin d'un compteur:

$counter = 1;

Les widgets sont numérotés . Ces numéros sont des identifiants secondaires pour WordPress.

Voyons le tableau pour le changer:

$active_widgets = get_option( 'sidebars_widgets' );

Nous avons aussi besoin d'un compteur (plus à ce sujet plus tard):

$counter = 1;

Et voici comment nous utilisons le compteur, les noms de la barre latérale et les arguments du widget (enfin, nous n’avons qu’un argument:) 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++;

Notez comment l'identificateur de widget est créé: le id_base, un moins -et le compteur. Le contenu du widget est stocké dans une autre variable $demo_widget_content. Voici le compteur la clé et les arguments du widget sont stockés dans un tableau.

Nous incrémentons le compteur de un lorsque nous avons terminé pour éviter les collisions.

C'était facile. Maintenant un widget RSS. Plus de champs, plus de plaisir!

$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++;

Voici quelque chose de nouveau: update_option()cela stockera l'argument du widget RSS dans une option séparée. WordPress les trouvera automatiquement plus tard.
Nous n'avons pas enregistré les arguments du widget de démonstration car nous avons ajouté une deuxième instance à notre deuxième barre latérale maintenant…

// 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 );

… Et conservez tous les arguments pour le tout t5_demo_widgeten un. Pas besoin de mettre à jour la même option deux fois.

Eh bien, assez de widgets pour aujourd'hui, sauvons le sidebars_widgetsaussi:

update_option( 'sidebars_widgets', $active_widgets );

Maintenant, WordPress saura qu'il existe des widgets enregistrés et où sont stockés les arguments de chaque widget. Un var_export()des sidebar_widgets ressemblera à ceci:

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,
)

Le code complet à nouveau:

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 vous allez wp-admin/widgets.phpmaintenant, vous verrez trois widgets prédéfinis:

capture d'écran des widgets actifs

Et c'est tout. Utilisation …

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

… Pour imprimer les widgets.

Il y a un petit problème: vous devez charger le front-end deux fois pour l'enregistrement initial. Si quelqu'un peut aider ici, je vous en serai très reconnaissant.

fuxia
la source
C’est vraiment intéressant .. mais ce code n’ajouterait-il pas un "nouveau" widget à chaque chargement de page `? De plus, un autre problème intéressant est de savoir comment contrôler ces widgets, y compris leur contenu depuis un plugin plutôt que par thème (chargement plus tôt?)
krembo99
1
@ krembo99 Les widgets ne sont pas ajoutés lorsque les barres latérales ne sont pas vides. Le code fonctionne dans un plugin exactement de la même manière.
fuxia
À quoi fait-on widget_t5_demo_widgetréférence ici update_option( 'widget_t5_demo_widget', $demo_widget_content );:?
Snowcrash
@SnowCrash C'est juste un nom d'option, aucune référence à autre chose.
fuxia
3

Merci de partager votre solution. J'ai utilisé ce qui a été décrit dans cette question pour créer un morceau de code qui peut être utilisé pour initialiser très facilement des barres latérales. C'est très flexible, vous pouvez créer autant de widgets que vous voulez sans avoir à modifier le code. Utilisez simplement les crochets de filtre et passez des arguments dans un tableau. Voici le code commenté:

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'] );

  }

}

Il s'agit d'une fonction d'assistance qui vérifie si la barre latérale contient déjà du contenu:

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;

}

Nous devons maintenant créer une fonction liée à l’action '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 ) );

}

Et maintenant l'initialisation du 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 dernière action consiste à créer les widgets dans chaque barre latérale:

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;

  }

}

Cette fonction permet de savoir combien d'instances d'un widget spécifique ont déjà été définies:

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;

}

La dernière chose à faire est d’attribuer des valeurs. Utilisez les fonctions de filtre suivantes:

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;

}

Et:

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',
    ),
 );

}

Idéalement, vous appelez initialize_sidebars dans une fonction de configuration appelée lors de l'activation d'un plugin ou d'un thème, comme suit: Activation du thème:

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

Activation du plugin:

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

Pour résumer l’utilisation de ce conglomérat de fonctions:

  1. créez une fonction qui initialise les barres latérales qui est connectée au filtre 'alter_initialization_sidebars'.

  2. créez une fonction pour chaque barre latérale que vous venez d'ajouter, qui est liée au filtre 'alter_initialization_widgets_ $ sidebarname'. Remplacez $ sidebarname par le nom de chaque barre latérale créée à l'étape 1.

Vous pouvez également simplement copier ce code non commenté dans votre fichier de fonctions et commencer à créer vos fonctions de filtrage immédiatement: Code sur pastie (sans fonctions de filtrage d'initialisation)

BdN3504
la source
2

Tout d’abord, merci à @toscho pour la réponse détaillée.

Ceci est un exemple simple pour ceux qui recherchent une solution simple et des options de widget par défaut:

$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
}

Remarque 1: Vous pouvez accéder sidebar-idau menu des widgets et inspecter la barre latérale souhaitée. Le premier <div id="widgets-holder-wrap">est <div>enfant asidebar-id .

Remarque 2: Vous pouvez accéder widget_nameau menu des widgets et inspecter le widget souhaité. Vous verrez quelque chose comme <div id="widget-6_widget_name-__i__" class="widget ui-draggable">.

Je souhaite que cela aide.

Manolo
la source
0

Voici comment vous le faites:

(ATTENTION, ceci pourrait ENLEVER tous les widgets précédents si vous ne remettiez pas les widgets d'origine dans le widgetstableau.)

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

Le numéro peut être utilisé si vous souhaitez ajouter ultérieurement des options au widget avec quelque chose comme:

    update_option('widget_widget_name', array(
    1 => array(
        'title' => 'The tile',
        'number' => 4
    ),
    '_multiwidget' => 1
));
its_me
la source
1
NE SUIVEZ PAS CELA, JE NE PEUX PAS TAUX CELA. TOUS MES WIDGETS SE DISPARUENT APRÈS L’UTILISATION DE CE CODE.
EresDev
Vous devez d'abord obtenir le tableau de widgets existant, sinon vous les effacerez tous comme indiqué dans le commentaire ci-dessus. $widgets = get_option( 'sidebars_widgets' );
cowgill