Adăugarea programatică a widget-urilor în bare laterale
Aș dori să adaug programatic widget-uri în cele două bare laterale pe care le am. Nu am putut găsi nicio modalitate oficială de a face acest lucru?
Am început să caut în baza de date. Am descoperit că opțiunea 'sidebars_widgets' este cea care plasează widget-urile în barele laterale. Când mă uit la opțiuni, numele widget-urilor au un număr adăugat la sfârșit, de exemplu: widget_name-6. De unde provine acel număr?
Are cineva vreo idee cum să rezolv această problemă?

Când am început acest răspuns, trebuia să fie doar o mică notă. Ei bine, am eșuat. Îmi pare rău! Rămâi cu mine, este un mic dar ascuns adânc...
Cum sunt stocate widget-urile în WordPress
Lista de widget-uri este stocată într-o opțiune numită 'sidebars_widgets'
. Un var_export()
poate afișa ceva similar cu următorul exemplu:
array (
'wp_inactive_widgets' =>
array (
),
'top-widget' =>
array (
),
'bottom-widget' =>
array (
),
'array_version' => 3,
)
Ignoră 'wp_inactive_widgets'
și 'array_version'
. Nu trebuie să ne îngrijorăm de acestea.
Celelalte chei sunt identificatori pentru barele laterale înregistrate. În acest caz, barele laterale au fost înregistrate cu următorul cod:
// Înregistrăm două bare laterale.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
register_sidebar(
array (
'name' => $sidebar,
'id' => $sidebar,
'before_widget' => '',
'after_widget' => ''
)
);
}
Implicit, barele laterale sunt goale după înregistrare. Bineînțeles.
Pentru fiecare clasă de widget înregistrată, se creează o opțiune separată care conține toate setările necesare. Opțiunea este prefixată cu șirul widget_
. Pentru a obține setările pentru toate widget-urile RSS active, trebuie să căutăm în...
get_option( 'widget_rss' );
Posibil rezultat:
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,
),
)
Observă numărul 2. Argumentele pentru mai multe instanțe sunt stocate în această singură opțiune, sortate după numere.
Pentru a vedea ce clase de widget sunt deja cunoscute de WordPress, mergi la wp-admin/options.php
și derulează până găsești ceva similar cu:
Da, date serializate. Nu, nu le poți citi aici. Nu-ți face griji, nu trebuie.
Un widget demo
Pentru a ilustra mai bine funcționarea internă, am scris un widget demo foarte simplu:
/**
* Widget super simplu.
*/
class T5_Demo_Widget extends WP_Widget
{
public function __construct()
{ // id_base , nume vizibil
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
);
}
}
Observă constructorul: 't5_demo_widget'
este $id_base
, identificatorul pentru acest widget. După cum poți vedea în captura de ecran, argumentele sale sunt stocate în opțiunea widget_t5_demo_widget
. Toate widget-urile tale personalizate vor fi tratate la fel. Nu trebuie să ghicești numele. Și din moment ce tu ai scris widget-urile tale (probabil), cunoști toate argumentele din parametrii $instance
ai clasei tale.
Bazele temei
Mai întâi trebuie să înregistrezi câteva bare laterale și widget-ul personalizat. Acțiunea potrivită pentru aceasta este ușor de reținut: 'widgets_init'
. Pune totul într-un container – o clasă sau o funcție. Pentru simplitate, voi folosi o funcție numită t5_default_widget_demo()
.
Tot codul următor merge în functions.php
. Clasa T5_Demo_Widget
ar trebui să fie deja încărcată. Am pus-o în același fișier...
add_action( 'widgets_init', 't5_default_widget_demo' );
function t5_default_widget_demo()
{
// Înregistrăm propriul nostru widget.
register_widget( 'T5_Demo_Widget' );
// Înregistrăm două bare laterale.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
register_sidebar(
array (
'name' => $sidebar,
'id' => $sidebar,
'before_widget' => '',
'after_widget' => ''
)
);
}
Până aici, simplu. Tema noastră este acum pregătită pentru widget-uri, widget-ul demo este cunoscut. Acum distracția.
$active_widgets = get_option( 'sidebars_widgets' );
if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
or ! empty ( $active_widgets[ $sidebars['b'] ] )
)
{ // Okay, nu mai e distractiv. Există deja conținut.
return;
}
Nu vrei să distrugi setările utilizatorului. Dacă există deja conținut în barele laterale, codul tău nu ar trebui să le suprascrie. De aceea ne oprim în acest caz.
Okay, presupunând că barele laterale sunt goale... avem nevoie de un contor:
$counter = 1;
Widget-urile sunt numerotate. Aceste numere sunt al doilea identificator pentru WordPress.
Să obținem array-ul pentru a-l modifica:
$active_widgets = get_option( 'sidebars_widgets' );
Avem nevoie și de un contor (mai multe despre asta mai târziu):
$counter = 1;
Și iată cum folosim contorul, numele barelor laterale și argumentele widget-ului (ei bine, avem doar un argument: text
).
// Adăugăm un widget 'demo' în bara laterală de sus...
$active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
// ...și scriem ceva text în el:
$demo_widget_content[ $counter ] = array ( 'text' => "Funcționează!\n\nUimitor!" );
$counter++;
Observă cum este creat identificatorul widget-ului: id_base
, un minus -
și contorul. Conținutul widget-ului este stocat într-o altă variabilă $demo_widget_content
. Aici contorul este cheia și argumentele widget-ului sunt stocate într-un array.
Incrementăm contorul cu unu când am terminat pentru a evita coliziunile.
Asta a fost ușor. Acum un widget RSS. Mai multe câmpuri, mai multă distracție!
$active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
// Ultimele 15 întrebări de la 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++;
Aici este ceva nou: update_option()
va stoca argumentele widget-ului RSS într-o opțiune separată. WordPress le va găsi automat mai târziu.
Nu am salvat argumentele widget-ului demo pentru că adăugăm o a doua instanță în a doua noastră bară laterală acum...
// Okay, acum la a doua noastră bară laterală. Să o facem scurtă.
$active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
#$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
$demo_widget_content[ $counter ] = array ( 'text' => 'A doua instanță a uimitorului nostru widget demo.' );
update_option( 'widget_t5_demo_widget', $demo_widget_content );
...și salvăm toate argumentele pentru t5_demo_widget
dintr-o dată. Nu este nevoie să actualizăm aceeași opțiune de două ori.
Ei bine, destule widget-uri pentru astăzi, să salvăm și sidebars_widgets
:
update_option( 'sidebars_widgets', $active_widgets );
Acum WordPress va ști că există câteva widget-uri înregistrate și unde sunt stocate argumentele pentru fiecare widget. Un var_export()
pe sidebars_widgets va arăta astfel:
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,
)
add_action( 'widgets_init', 't5_default_widget_demo' );
function t5_default_widget_demo()
{
// Înregistrăm propriul nostru widget.
register_widget( 'T5_Demo_Widget' );
// Înregistrăm două bare laterale.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
register_sidebar(
array (
'name' => $sidebar,
'id' => $sidebar,
'before_widget' => '',
'after_widget' => ''
)
);
}
// Okay, acum partea distractivă.
// Nu vrem să anulăm modificările utilizatorului, așa că căutăm mai întâi modificări.
$active_widgets = get_option( 'sidebars_widgets' );
if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
or ! empty ( $active_widgets[ $sidebars['b'] ] )
)
{ // Okay, nu mai e distractiv. Există deja conținut.
return;
}
// Barele laterale sunt goale, să punem ceva în ele.
// Ce zici de un widget RSS și două instanțe ale widget-ului nostru demo?
// Observă că widget-urile sunt numerotate. Avem nevoie de un contor:
$counter = 1;
// Adăugăm un widget 'demo' în bara laterală de sus...
$active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
// ...și scriem ceva text în el:
$demo_widget_content[ $counter ] = array ( 'text' => "Funcționează!\n\nUimitor!" );
#update_option( 'widget_t5_demo_widget', $demo_widget_content );
$counter++;
// Asta a fost ușor. Acum un widget RSS. Mai multe câmpuri, mai multă distracție!
$active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
// Ultimele 15 întrebări de la 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, acum la a doua noastră bară laterală. Să o facem scurtă.
$active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
#$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
$demo_widget_content[ $counter ] = array ( 'text' => 'A doua instanță a uimitorului nostru widget demo.' );
update_option( 'widget_t5_demo_widget', $demo_widget_content );
// Acum salvăm array-ul $active_widgets.
update_option( 'sidebars_widgets', $active_widgets );
}
Dacă mergi acum la wp-admin/widgets.php
, vei vedea trei widget-uri pre-setate:
Și asta este. Folosește...
dynamic_sidebar( 'top-widget' );
dynamic_sidebar( 'bottom-widget' );
...pentru a afișa widget-urile.
Există o mică problemă: Trebuie să încarci front-end-ul de două ori pentru înregistrarea inițială. Dacă cineva poate ajuta aici, voi fi foarte recunoscător.

Acest lucru este cu adevărat interesant... dar nu ar adăuga acest cod un "nou" widget la fiecare încărcare de pagină? De asemenea, o altă problemă interesantă este cum poate cineva controla acele widget-uri, inclusiv conținutul lor, dintr-un plugin în locul temei (se încarcă mai devreme?).

@krembo99 Widget-urile nu sunt adăugate atunci când bara laterală nu este goală. Codul funcționează la fel într-un plugin.

La ce se referă widget_t5_demo_widget
aici: update_option( 'widget_t5_demo_widget', $demo_widget_content );
?

@SnowCrash Acesta este doar un nume de opțiune, fără nicio referire la altceva.

Am găsit acest răspuns informativ pentru a înțelege cum sunt stocate/folosite datele. Apoi, mi-a plăcut acest alt răspuns pentru exemplul practic de cod: https://wordpress.stackexchange.com/a/138248/27896

Mulțumesc pentru soluția oferită. Am folosit ceea ce a fost descris în această întrebare pentru a crea o bucată de cod care poate fi utilizată pentru a inițializa barele laterale foarte ușor. Este foarte flexibil, puteți crea câte widget-uri doriți fără a fi nevoie să modificați codul deloc. Doar folosiți filtrele hook și transmiteți argumentele într-un array. Iată codul comentat:
function initialize_sidebars(){
$sidebars = array();
// Furnizați barele laterale pe care doriți să le inițializați într-un filtru
$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;
// transmitem argumentele noastre ca referință, astfel încât să le putem modifica conținutul
do_action( 'your_plugin_sidebar_init', array( &$args ) );
}
// trebuie să actualizăm barele laterale doar dacă acestea nu au fost încă inițializate
// și avem și date cu care să inițializăm barele laterale
if ( ! empty( $args['update_widget_content'] ) ) {
foreach ( $args['update_widget_content'] as $widget => $widget_occurence ) {
// array-ul update_widget_content stochează toate instanțele fiecărui widget
update_option( 'widget_' . $widget, $args['update_widget_content'][ $widget ] );
}
// după ce am actualizat toate widget-urile, actualizăm array-ul active_widgets
update_option( 'sidebars_widgets', $args['active_widgets'] );
}
}
Aceasta este o funcție helper care verifică dacă bara laterală are deja conținut:
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;
}
Acum trebuie să creăm o funcție care este conectată la acțiunea 'sidebar_init'.
add_action( 'your_plugin_sidebar_init', 'add_widgets_to_sidebar' );
function add_widgets_to_sidebar( $args ) {
extract( $args[0] );
// Verificăm dacă bara laterală curentă are deja conținut și dacă are, ieșim
$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 ) );
}
Și acum inițializarea widget-urilor:
add_action( 'your_plugin_widget_init', 'your_plugin_initialize_widgets' );
function your_plugin_initialize_widgets( $args ) {
extract( $args[0][0] );
$widgets = array();
// Aici sunt inițializate widget-urile definite anterior în funcțiile de filtru,
// dar numai cele corespunzătoare barei laterale curente
$widgets = apply_filters( 'alter_initialization_widgets_' . $current_sidebar_short_name, $widgets );
if ( ! empty( $widgets ) ) {
do_action( 'create_widgets_for_sidebar', array( &$args ), $widgets );
}
}
Ultima acțiune este de a crea widget-urile în fiecare bară 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 ) {
// Contorul este incrementat pe baza fiecărui widget. De exemplu, dacă ați avea trei widget-uri,
// două dintre ele fiind widget-ul de arhivă și unul fiind un widget personalizat, atunci
// contorul corect atașat fiecăruia ar fi archive-1, archive-2 și custom-1.
// Deci contorul widget-ului nu este un contor global, ci unul care numără instanțele
// (widget_occurrence cum l-am numit eu) fiecărui widget.
$counter = count_widget_occurence( $widget, $args[0][0][0]['update_widget_content'] );
// Adăugăm fiecare instanță la widget-urile active...
$args[0][0][0]['active_widgets'][ $sidebars[ $current_sidebar_short_name ] ][] = $widget . '-' . $counter;
// ...și salvăm și conținutul într-un alt array asociativ.
$args[0][0][0]['update_widget_content'][ $widget ][ $counter ] = $widget_content;
}
}
Această funcție este folosită pentru a ține evidența câte instanțe ale unui anumit widget au fost deja definite:
function count_widget_occurence( $widget, $update_widget_content ) {
$widget_occurrence = 0;
// Ne uităm la array-ul update_widget_content care stochează fiecare
// instanță a widget-ului curent cu contorul curent într-un
// array asociativ. Cheia acestui array este numele
// widget-ului curent.
// De exemplu, trei widget-uri de arhivă ar arăta astfel:
// '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;
}
Ultimul lucru pe care trebuie să-l facem este să atribuim valori. Folosiți aceste funcții de filtru:
add_filter( 'alter_initialization_sidebars', 'current_initialization_sidebars' ) ;
// Folosiți acest hook de filtru pentru a specifica ce bare laterale doriți să inițializați
function current_initialization_sidebars( $sidebars ) {
// Barele laterale sunt atribuite în acest mod.
// Cheia array-ului este foarte importantă deoarece este folosită ca sufix în funcția de inițializare
// pentru fiecare bară laterală. Valoarea este ceea ce este folosit în atributele HTML.
$sidebars['info'] = 'info-sidebar';
return $sidebars;
}
Și:
add_filter( 'alter_initialization_widgets_info', 'current_info_widgets' );
// Adăugați un hook de filtru pentru fiecare bară laterală pe care o aveți. Numele hook-ului este derivat din
// cheile array-ului transmise în filtrul alter_initialization_sidebars.
// Fiecare filtru are un nume de forma 'alter_initialization_widgets_' cu cheia
// array-ului atașată.
function current_info_widgets( $widgets ) {
// Această funcție de filtru este folosită pentru a adăuga widget-uri la bara laterală info. Adăugați fiecare widget
// pe care doriți să-l atribuiți acestei bare laterale într-un array.
return $widgets = array(
// Folosiți numele widget-ului așa cum este specificat în apelul către constructorul WP_Widget
// ca și cheie a array-ului.
// Widget-ul de arhivă este un widget care este inclus implicit în WordPress.
// Argumentele folosite de acest widget, ca și toate celelalte widget-uri implicite, pot fi găsite
// în wp-includes/default-widgets.php.
'archives' => array(
// Transmiteți opțiunile array-ului ca un array
'title' => 'Conținut Vechi',
'dropdown' => 'on',
// Valoarea 'on' este aleasă arbitrar, widget-ul verifică de fapt doar dacă
// există o valoare nevidă pentru ambele opțiuni
'count' => 'on',
),
);
}
În mod ideal, ați apela initialize_sidebars într-o funcție de setup care este apelată la activarea plugin-ului sau a temei astfel: Activarea temei:
add_action( 'after_switch_theme', 'my_activation_function' );
function my_activation_function() {
initialize_sidebars();
}
Activarea plugin-ului:
register_activation_hook( __FILE__, 'my_activation_function' );
function my_activation_function() {
initialize_sidebars();
}
Pentru a rezuma utilizarea acestui conglomerat de funcții:
creați o funcție care inițializează barele laterale care este conectată la filtrul 'alter_initialization_sidebars'.
creați o funcție pentru fiecare bară laterală pe care tocmai ați adăugat-o, care este conectată la filtrul 'alter_initialization_widgets_$sidebarname'. Înlocuiți $sidebarname cu numele fiecărei bare laterale pe care ați creat-o în pasul 1.
Puteți, de asemenea, să copiați pur și simplu acest cod necomentat în fișierul dvs. functions și să începeți să creați funcțiile dvs. de filtru imediat: Cod pe pastie (fără funcțiile de filtru de inițializare)

În primul rând, mulțumesc lui @toscho pentru răspunsul detaliat.
Acesta este un exemplu simplu pentru cei care caută o soluție simplă și opțiuni implicite pentru widget-uri:
$active_sidebars = get_option( 'sidebars_widgets' ); //obține toate barele laterale și widget-urile
$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'])) { //verifică dacă bara laterală există și este goală
$active_sidebars['sidebar-id'] = array('widget_name-1'); //adaugă un widget în bara laterală
update_option('widget_name-1', $widget_options); //actualizează opțiunile implicite ale widget-ului
update_option('sidebars_widgets', $active_sidebars); //actualizează barele laterale
}
Notă 1: Puteți obține sidebar-id
mergând în meniul widget-urilor și inspectând bara laterală dorită. Primul <div>
copil al <div id="widgets-holder-wrap">
conține sidebar-id
.
Notă 2: Puteți obține widget_name
mergând în meniul widget-urilor și inspectând widget-ul dorit. Veți vedea ceva de genul <div id="widget-6_widget_name-__i__" class="widget ui-draggable">
.
Sper că vă ajută.

Așa se face:
(ATENȚIE, acest lucru ar putea ELIMINA toate widget-urile anterioare dacă nu ai pus înapoi widget-urile originale în tabloul widgets
.)
$widgets = array(
'middle-sidebar' => array(
'widget_name'
),
'right-sidebar' => array(
'widget2_name-1'
)
);
update_option('sidebars_widgets', $widgets);
Numărul (-number) poate fi folosit dacă ulterior dorești să adaugi opțiuni la widget cu ceva de genul:
update_option('widget_widget_name', array(
1 => array(
'title' => 'Titlul',
'number' => 4
),
'_multiwidget' => 1
));

NU URMAȚI ACESTA, NU POT SĂ O EVALUEZ NEGATIV. TOATE WIDGET-URILE MELE AU DISPĂRUT DUPĂ CE AM FOLOSIT ACEST COD.
