it-swarm.com.de

Programmgesteuertes Hinzufügen von Widgets zu Seitenleisten

Ich möchte meinen beiden Seitenleisten, die ich habe, programmgesteuert Widgets hinzufügen. Ich konnte keinen offiziellen Weg finden, es zu tun?

Ich fing an, in der Datenbank zu suchen. Ich habe festgestellt, dass es die Option 'sidebars_widgets' ist, mit der Widgets in die Seitenleisten eingefügt werden. Wenn Sie sich die Optionen ansehen, wird dem Widget-Namen eine Nummer wie folgt hinzugefügt: widget_name-6. Woher kommt diese Nummer?

Irgendeine Idee, wie man das behebt?

61
Marlun

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 'sidebars_widgets' gespeichert. Eine var_export() kann etwa Folgendes ergeben:

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

Ignoriere 'wp_inactive_widgets' und 'array_version'. Wir müssen uns nicht darum kümmern.
Die anderen Schlüssel sind Kennungen 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 widget_ vorangestellt. 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,
  ),
)

Notieren Sie die Zahl 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:

screen shot of serialized widget options

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 der $id_base, der Bezeichner für dieses Widget. Wie Sie im Screenshot sehen können, werden die Argumente in der Option widget_t5_demo_widget gespeichert. Alle Ihre benutzerdefinierten Widgets werden so behandelt. Sie müssen den Namen nicht erraten. Und da Sie Ihre Widgets geschrieben haben (wahrscheinlich), kennen Sie alle Argumente aus den $instance-Parametern Ihrer Klasse.

Themengrundlagen

Zuerst müssen Sie einige Seitenleisten und das benutzerdefinierte Widget registrieren. Die richtige Aktion hierfü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 mit dem Namen t5_default_widget_demo().

Der gesamte folgende Code wird in den functions.php eingefügt. 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 Thema ist jetzt Widget bereit, 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: der id_base, ein Minus-- und der Zähler. Das content des Widgets wird in einer anderen Variablen $demo_widget_content gespeichert. Hier ist der Zähler der Schlüssel und die Widget-Argumente werden in einem Array gespeichert.

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() Damit 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 speichere alle Argumente für den t5_demo_widget in einem Rush. Dieselbe Option muss nicht zweimal aktualisiert werden.

Nun, genug Widgets für heute, speichern wir auch den 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. Eine 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 vollständigeCode 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 jetzt zu wp-admin/widgets.php gehen, sehen Sie drei voreingestellte Widgets:

screen shot of active widgets

Und das ist es. Benutzen …

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 jemand hier raushelfen kann, bin ich sehr dankbar.

89
fuxia

Vielen Dank, dass Sie Ihre Lösung geteilt haben. Ich habe das, was in dieser Frage beschrieben wurde, verwendet, um einen Code zu erstellen, mit dem Seitenleisten sehr einfach initialisiert werden können. Es ist sehr flexibel und Sie können so viele Widgets erstellen, wie Sie möchten, ohne den Code ändern zu müssen. Verwenden Sie einfach die Filter-Hooks und übergeben Sie Argumente in einem Array. Hier ist der kommentierte Code:

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

  }

}

Dies ist eine Hilfsfunktion, die prüft, ob die Seitenleiste bereits Inhalt enthält:

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;

}

Jetzt müssen wir eine Funktion erstellen, die mit der Aktion 'sidebar_init' verknüpft ist.

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

}

Und jetzt die Widget-Initialisierung:

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

  }

}

Die letzte Aktion besteht darin, die Widgets in jeder Seitenleiste zu erstellen:

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;

  }

}

Mit dieser Funktion können Sie verfolgen, wie viele Instanzen eines bestimmten Widgets bereits definiert wurden:

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;

}

Das Letzte, was wir tun müssen, ist, Werte zuzuweisen. Nutzen Sie diese Filterfunktionen:

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;

}

Und:

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

}

Im Idealfall würden Sie initialize_sidebars in einer Setup-Funktion aufrufen, die beim Aktivieren des Plugins oder des Themas wie folgt aufgerufen wird:

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

Plugin Aktivierung:

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

Um die Verwendung dieses Konglomerats von Funktionen zusammenzufassen:

  1. erstellen Sie eine Funktion, die die Seitenleisten initialisiert, die mit dem Filter 'alter_initialization_sidebars' verknüpft sind.

  2. erstellen Sie für jede soeben hinzugefügte Seitenleiste eine Funktion, die mit dem Filter "alter_initialization_widgets_ $ sidebarname" verknüpft ist. Ersetzen Sie $ sidebarname durch den Namen jeder Seitenleiste, die Sie in Schritt 1 erstellt haben.

Sie können diesen unkommentierten Code auch einfach in Ihre Funktionsdatei kopieren und sofort mit der Erstellung Ihrer Filterfunktionen beginnen: Code auf Pastete (ohne Initialisierungsfilterfunktionen)

3
BdN3504

Zunächst einmal vielen Dank an @toscho für die ausführliche Antwort.

Dies ist ein einfaches Beispiel für diejenigen, die nach einer einfachen Lösung und Standard-Widget-Optionen suchen:

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

Anmerkung 1: Sie können sidebar-id veranlassen, zum Widgets-Menü zu gehen und die gewünschte Seitenleiste zu inspizieren. Das <div id="widgets-holder-wrap"> Kind des ersten <div> hat den sidebar-id.

Hinweis 2: Sie können den widget_name zum Widgets-Menü gehen und das gewünschte Widget überprüfen. Sie werden so etwas wie <div id="widget-6_widget_name-__i__" class="widget ui-draggable"> sehen.

Ich wünschte, es hilft.

2
Manolo

Das ist wie man es macht:

(WARNUNG, dies könnte alle vorherigen Widgets ENTFERNEN, wenn Sie die ursprünglichen Widgets nicht in das Array widgets zurückgesetzt haben.)

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

Die -Nummer kann verwendet werden, wenn Sie dem Widget später Optionen wie folgt hinzufügen möchten:

    update_option('widget_widget_name', array(
    1 => array(
        'title' => 'The tile',
        'number' => 4
    ),
    '_multiwidget' => 1
));
0
its_me