Als ich mit dieser Antwort anfing, sollte es nur eine kleine Notiz sein. Nun, ich habe versagt. Es tut uns leid! Bleib bei mir, es gibt eine gute Sache, die tief in mir verborgen ist ...
Wie werden WordPress-Widgets gespeichert?
Die Liste der Widgets wird in einer Option mit dem Namen gespeichert 'sidebars_widgets'
. A var_export()
kann so etwas wie das Folgende geben:
array (
'wp_inactive_widgets' =>
array (
),
'top-widget' =>
array (
),
'bottom-widget' =>
array (
),
'array_version' => 3,
)
Ignorieren 'wp_inactive_widgets'
und 'array_version'
. Wir müssen uns nicht darum kümmern.
Die anderen Schlüssel sind Bezeichner für registrierte Seitenleisten. In diesem Fall wurden die Seitenleisten möglicherweise mit diesem Code registriert:
// 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' => ''
)
);
}
Standardmäßig sind die Seitenleisten nach der Registrierung leer. Na sicher.
Für jede registrierte Widgetklasse wird eine separate Option erstellt, die alle erforderlichen Optionen enthält. Der Option wird die Zeichenfolge vorangestellt widget_
. Um die Optionen für alle aktiven RSS-Widgets zu erhalten, müssen wir uns Folgendes ansehen:
get_option( 'widget_rss' );
Mögliche Ausgabe:
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,
),
)
Beachten Sie die Nummer 2 . Die Argumente für mehrere Instanzen werden in dieser einen Option nach Zahlen sortiert gespeichert.
Um zu sehen, welche Widget-Klassen WordPress bereits bekannt sind, gehen Sie zu wp-admin/options.php
und scrollen Sie nach unten, bis Sie so etwas sehen:
Ja, serialisierte Daten. Nein, die kannst du hier nicht lesen. Mach dir keine Sorgen, du musst nicht.
Ein Demo-Widget
Um das Innenleben besser zu veranschaulichen, habe ich ein sehr einfaches Demo-Widget geschrieben:
/**
* 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
);
}
}
Beachten Sie den Konstruktor: 't5_demo_widget'
ist die $id_base
, die Kennung für dieses Widget. Wie Sie im Screenshot sehen können, werden die Argumente in der Option gespeichert widget_t5_demo_widget
. Alle Ihre benutzerdefinierten Widgets werden so behandelt. Sie müssen den Namen nicht erraten. Und da Sie Ihre Widgets (wahrscheinlich) geschrieben haben, kennen Sie alle Argumente aus den $instance
Parametern Ihrer Klasse .
Themengrundlagen
Zuerst müssen Sie einige Seitenleisten und das benutzerdefinierte Widget registrieren. Die richtige Maßnahme dafür ist leicht zu merken: 'widgets_init'
. Legen Sie alles in einen Container - eine Klasse oder eine Funktion. Der Einfachheit halber verwende ich eine Funktion namens t5_default_widget_demo()
.
Der gesamte folgende Code geht in das functions.php
. Die Klasse T5_Demo_Widget
sollte bereits geladen sein. Ich habe es einfach in die gleiche Datei gelegt ...
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' => ''
)
);
}
So weit, so einfach. Unser Theme ist nun Widget-fähig, das Demo-Widget ist bekannt. Nun der Spaß.
$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;
}
Sie möchten die Benutzereinstellungen wirklich nicht zerstören. Wenn sich bereits Inhalte in den Seitenleisten befinden, sollte Ihr Code nicht darüber laufen. Deshalb hören wir in diesem Fall auf.
Okay, angenommen die Seitenleisten sind leer ... wir brauchen einen Zähler:
$counter = 1;
Widgets sind nummeriert . Diese Zahlen sind zweite Kennungen für WordPress.
Lassen Sie uns das Array ändern:
$active_widgets = get_option( 'sidebars_widgets' );
Wir brauchen auch einen Zähler (dazu später mehr):
$counter = 1;
Und hier ist, wie wir den Zähler, die Namen der Seitenleiste und die Widget-Argumente verwenden (nun, wir haben nur ein 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++;
Beachten Sie, wie die Widget-ID erstellt wird: das id_base
, ein Minus -
und der Zähler. Der Inhalt des Widgets wird in einer anderen Variablen gespeichert $demo_widget_content
. Hier ist der Zähler, in dem der Schlüssel und die Widget-Argumente in einem Array gespeichert sind.
Wir erhöhen den Zähler um eins, wenn wir fertig sind, um Kollisionen zu vermeiden.
Das war einfach. Jetzt ein RSS-Widget. Mehr Felder, mehr Spaß!
$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++;
Folgendes ist neu: update_option()
Dadurch wird das RSS-Widget-Argument in einer separaten Option gespeichert. WordPress findet diese später automatisch.
Wir haben die Argumente für das Demo-Widget nicht gespeichert, weil wir unserer zweiten Seitenleiste jetzt eine zweite Instanz hinzufügen ...
// 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 );
… Und speichern Sie alle Argumente für die t5_demo_widget
in einem Ansturm. Dieselbe Option muss nicht zweimal aktualisiert werden.
Nun, genug Widgets für heute, speichern wir auch die sidebars_widgets
:
update_option( 'sidebars_widgets', $active_widgets );
Jetzt weiß WordPress, dass es einige registrierte Widgets gibt und wo die Argumente für jedes Widget gespeichert sind. A var_export()
auf den sidebar_widgets sieht so aus:
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,
)
Der komplette Code nochmal:
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 );
}
Wenn Sie wp-admin/widgets.php
jetzt gehen, sehen Sie drei voreingestellte Widgets:
Und das ist es. Verwenden …
dynamic_sidebar( 'top-widget' );
dynamic_sidebar( 'bottom-widget' );
… Um die Widgets auszudrucken.
Es gibt eine kleine Panne: Sie müssen das Frontend für die Erstregistrierung zweimal laden. Wenn hier jemand helfen kann, bin ich sehr dankbar.