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.php
et faites défiler l'écran jusqu'à ce que vous voyiez quelque chose comme ceci:
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_base
l'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 $instance
paramè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_Widget
devrait 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_widget
en un. Pas besoin de mettre à jour la même option deux fois.
Eh bien, assez de widgets pour aujourd'hui, sauvons le sidebars_widgets
aussi:
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.php
maintenant, vous verrez trois widgets prédéfinis:
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.