In questo tutorial, daremo un'occhiata da vicino sotto il cofano del widget di testo WordPress per scoprire il processo di creando un widget che può essere aggiunto a più posizioni di widget.
Se conosci le basi della programmazione in PHP, la creazione di un widget WordPress non è affatto difficile. Ho spiegato le basi in un precedente tutorial, The Anatomy of a WordPress Plugin: è una buona idea controllarne uno prima di leggere ulteriormente, se non hai ancora costruito un widget.
Mentre quel modo basilare di creare un widget è abbastanza buono per molti plugin, ha uno svantaggio principale: il widget può essere aggiunto a un solo spazio in un blog.
Se aggiungi il widget a una delle barre laterali, il pulsante "Aggiungi" del widget scompare e il widget non può essere aggiunto a nessun altro slot prima di rimuoverlo dal primo.
In alcuni casi, non è un problema, perché la natura del widget è che viene mostrata una sola volta. Ad esempio, è abbastanza OK elencare solo l'archivio del blog in un posto nel layout. Ma ci sono molti casi in cui più di un'istanza può essere molto utile. Uno di questi esempi è il widget Testo fornito in bundle con WordPress.
Il widget Testo è un semplice widget che ti consente di specificare un'intestazione e un testo, consentendo anche l'HTML, e il rendering dei suoi contenuti nella barra laterale del blog. Grazie a questa semplicità, il widget può essere utilizzato per una vasta gamma di scopi. Ad esempio, nella prossima immagine - uno screenshot dal mio blog personale - puoi vedere come uso il widget di testo nella barra laterale per mostrare un testo di benvenuto, e poi di nuovo per mostrare alcuni annunci nella parte inferiore della barra laterale. Nella documentazione di WordPress, vengono chiamati widget come questo "multi-widgets".
Poiché WordPress è un progetto open source, possiamo scavare nel codice sorgente e utilizzarlo come riferimento per i nostri progetti. Per questo tutorial, possiamo dare un'occhiata più da vicino al widget Testo e vedere come è stato implementato, utilizzandolo come esempio per trasformare i nostri widget in multi-widgets.
Il primo passo è cercare attraverso il codice di WordPress e localizzare il widget di testo. È un passo interessante e ti consiglio di controllare alcuni altri file qui e là per avere un'idea generale di ciò che accade all'interno della piattaforma di blogging.
Ma se non vedi l'ora di agire, ecco dove troverai il codice del widget:
wordpress / wp-includes / widgets.php
Apri il file e scorri fino alla fine di esso, attorno alla riga 1958 (nella versione 2.7.1), e lì, nascosto nel mezzo del codice sorgente, troverai un widget di esempio, commentato ed etichettato come "Pattern for multi-widget" (consente più istanze come il widget di testo). "
All'inizio, il codice di esempio può sembrare piuttosto scoraggiante, quindi lo esamineremo riga per riga, dando un senso alle idee attorno alle quali è costruito il modello. I frammenti di codice in questo tutorial sono stati copiati dal modello di esempio, ma ho apportato alcune piccole modifiche qua e là per rendere il codice più facile da seguire (dividendo principalmente le linee lunghe a quelle più brevi). Oltre a questi piccoli aggiustamenti, il codice sorgente è esattamente lo stesso di quello che aprirai widgets.php
dalla base di codice WordPress.
Quando l'utente preme il pulsante "Salva modifiche" nel menu Widget, WordPress raccoglie i parametri del modulo da ciascun widget elencato nelle barre laterali e li invia a ciascuno dei widget registrati. Questa funzione rende possibile la creazione di widget multipli: quando la funzione del controller widget viene notificata per salvare un'istanza widget, tutti i parametri vengono passati ad esso e può aggiornare ogni istanza di questo tipo di widget contemporaneamente, aggiungendone di nuovi e rimuovere quelli non utilizzati, se necessario.
Analizzeremo brevemente i dettagli del processo di salvataggio, ma in primo luogo, un buon punto di partenza per osservare come vengono archiviati i dati del widget per un multi-widget è osservare la parte del codice in cui vengono utilizzati i dati . Ecco il codice per il metodo utilizzato per mostrare un'istanza del widget di esempio:
$ widget_args); $ widget_args = wp_parse_args ($ widget_args, array ('numero' => -1)); estratto ($ widget_args, EXTR_SKIP); // I dati dovrebbero essere archiviati come array $ options = get_option ('widget_many'); se (! isset ($ options [$ number])) restituisce; echo $ before_widget; // Fai cose per questo widget, disegnando i dati da $ options [$ number] echo $ after_widget; ?>
Il primo parametro passato alla funzione di rendering del widget, $ args
, contiene le impostazioni generiche dei widget, ad esempio cosa deve essere stampato prima e dopo il widget e come deve essere formattata l'intestazione del widget. Il codice sulla riga 3 viene utilizzato per suddividere tali informazioni in variabili locali, da cui $ before_widget
e $ after_widget
sono utilizzati nell'esempio.
Il secondo parametro, $ widget_args
è più interessante per noi: contiene l'id dell'istanza del widget da rendere. Le righe dalla 4 alla 7 sono lì per assicurarsi che il parametro sia in un formato corretto e che alla fine, dopo il estratto
chiama sulla linea 7, possiamo trovare l'indice del widget nella variabile locale numero di $
.
Proprio come le impostazioni del widget per un semplice widget di una sola volta, le impostazioni per un'istanza di widget vengono archiviate come una matrice contenente coppie chiave-valore per ogni impostazione. Ma come ora abbiamo bisogno di memorizzare più istanze, invece di salvare ogni array con la propria chiamata a update_option
, li abbiamo messi tutti in un array usando l'id di istanza (numero di $
) come indice e quindi salvare il tutto con l'id del tipo di widget.
Nell'esempio sopra, abbiamo un widget chiamato "widget_many
", e diciamo che abbiamo aggiunto tre istanze di esso alla nostra barra laterale del blog. Quando si esegue il rendering di uno di questi, prima otteniamo un array contenente tutto il widget_many
istanze chiamando get_option ( 'widget_many');
(riga 10) e quindi trovare i dati per l'istanza corrente da quella matrice (riga 16).
Il codice di esempio da non mostra le specifiche di ciò che dovresti fare con i dati, quindi diamo un'occhiata al widget di testo attuale per maggiori informazioni:
$ widget_args); $ widget_args = wp_parse_args ($ widget_args, array ('numero' => -1)); estratto ($ widget_args, EXTR_SKIP); $ options = get_option ('widget_text'); se (! isset ($ options [$ number])) restituisce; $ title = apply_filters ('widget_title', $ options [$ number] ['title']); $ text = apply_filters ('widget_text', $ options [$ number] ['text']); ?>
Sulle righe 13 e 14, è possibile vedere come vengono letti i due parametri necessari per il widget di testo dalle opzioni numero di $
come id di esempio. E sulle dieci linee successive, i parametri vengono visualizzati sullo schermo.
Analizzando la funzione di rendering dei widget, abbiamo ora scoperto le basi dietro il salvataggio dei dati per un multi-widget:
Ora, guarderemo più da vicino e vedremo i trucchi e i caveat coinvolti.
Utilizzando lo stesso approccio di prima, esamineremo ora la funzione utilizzata per mostrare e gestire i moduli delle impostazioni e analizzarli riga per riga. Questa funzione, widget_many_control
, è la funzione che salva le impostazioni e rende il modulo delle impostazioni per il widget di esempio "widget_many". Si chiama una volta per ciascuno widget_many
istanza, passando sempre l'id di istanza in $ widget_args
.
Poiché la funzione fa parte della gestione dell'invio del modulo, il comando $ _POST
l'array conterrà tutti i parametri che sono stati inviati utilizzando il modulo di modifica del widget.
$ widget_args); $ widget_args = wp_parse_args ($ widget_args, array ('numero' => -1)); estratto ($ widget_args, EXTR_SKIP);
Sulle prime righe della funzione, vedrai qualcosa di familiare (righe 6-9). Questo è lo stesso pezzo di codice che è stato usato nella funzione di rendering per essere sicuro numero di $
è stato inizializzato con l'id numerico dell'istanza del widget corrente.
Ma come noterai presto, non ci servirà quell'indice per nient'altro che il rendering del modulo di modifica del widget, dato che salviamo sempre ogni istanza del tipo di widget "widget_many" in un ciclo.
Successivamente, recupereremo le impostazioni del widget corrente, creandole se non esistono:
$ options = get_option ('widget_many'); if (! is_array ($ options)) $ options = array ();
Quando si implementa il proprio widget, ricordarsi di cambiare la chiave, widget_many
all'ID del proprio widget. Oltre a questo, questo codice può essere riutilizzato così com'è. Sulle righe 2 e 3, il codice si prende cura del caso quando stiamo aggiungendo la prima istanza di widget di questo tipo creando una matrice di opzioni vuota da usare.
Se le impostazioni sono già state salvate almeno per un'istanza, le otteniamo da get_option
e può continuare ad aggiornare le impostazioni se è stato inviato un modulo:
if (! $ updated &&! empty ($ _ POST ['sidebar']))
La riga precedente ha due funzioni: controlla se i dati sono stati pubblicati ("!empty ($ _ POST [ 'sidebar'])
") e si assicura che le istanze di questo tipo di widget vengano gestite una sola volta.
Il sistema di widget chiama la funzione di gestione dei widget una volta per ogni istanza di widget, ma poiché dobbiamo occuparci di cose come l'aggiunta e la rimozione di nuove istanze di widget, non possiamo farlo senza conoscere tutti i widget di questo tipo esistenti. Questo è il motivo per cui l'approccio consiste nell'aggiornare ogni istanza di widget di questo tipo alla prima occorrenza e quindi impostare la variabile globale $ aggiornata
true, in modo che l'istanza successiva non esegua di nuovo l'aggiornamento.
// Ci dice quale barra laterale inserire i dati in $ sidebar = (stringa) $ _POST ['sidebar']; $ sidebars_widgets = wp_get_sidebars_widgets (); if (isset ($ sidebars_widgets [$ sidebar])) $ this_sidebar = & $ sidebars_widgets [$ sidebar]; altrimenti $ this_sidebar = array (); foreach ($ this_sidebar as $ _widget_id) $ widget = $ wp_registered_widgets [$ _ widget_id]; if ('widget_many' == $ widget ['callback'] && isset ($ widget ['params'] [0] ['numero'])) $ widget_number = $ widget ['params'] [0] [' numero']; if (! in_array ("many- $ widget_number", $ _POST ['widget-id'])) unset ($ options [$ widget_number]); // Compila i dati da $ widget_many_instance $ widget_data = (array) $ _POST ['widget-many']; foreach ($ widget_data as $ widget_number => $ widget_many_instance) if (! isset ($ widget_many_instance ['something']) && isset ($ options [$ widget_number])) // utente cliccato annulla continua; $ something = wp_specialchars ($ widget_many_instance ['something']); $ opzioni [$ widget_number] = array ('qualcosa' => $ qualcosa); update_option ('widget_many', $ options); $ updated = true; // Quindi non ne parleremo più di una volta
Questo snippet di codice cerca dapprima tutti i widget memorizzati nella barra laterale che viene aggiornata (righe 2-8) e quindi passa attraverso l'elenco rimuovendo tutti quelli che corrispondono all'id widget di questo tipo di widget (righe 10-18).
$ _POST ( "sidebar")
(riga 2) contiene l'id della barra laterale. In questo modo, se l'utente ha rimosso un widget, verrà eliminato anche dai dati. Eliminando tutto, ci assicuriamo di non lasciare accidentalmente dei duplicati, ad esempio se l'ID di alcuni widget è cambiato tra gli aggiornamenti.
Dopo aver rimosso tutto, iniziamo ad aggiungere i widget che sono stati postati dall'utente. Nel modulo pubblicato, c'è una matrice contenente tutti i dati per ogni istanza del tipo di widget. La matrice è organizzata in questo modo:
['widget-many'] => [0] => parametri per l'istanza widget 0 (array), [1] => parametri per l'istanza widget 1 (array), ...
Sulle righe 23-31, il codice scorre i dati dell'istanza del widget inviati e crea le impostazioni per ciascuna istanza (righe 29 e 30). Poiché questo è solo un codice di esempio, la parte di salvataggio utilizza dati segnaposto come "qualcosa". Quindi, diamo nuovamente un'occhiata al widget di testo per vedere come funziona con i dati reali:
$ title = strip_tags (stripslashes ($ widget_text ['title'])); if (current_user_can ('unfiltered_html')) $ text = stripslashes ($ widget_text ['testo']); else $ text = stripslashes (wp_filter_post_kses ($ widget_text ['text'])); $ options [$ widget_number] = compact ('title', 'text');
Il widget di testo ha due parametri: titolo
e testo
. Il $ widget_text
variabile in questo pezzo di codice è usato allo stesso modo di $ widget_many_instance
nel codice di esempio che abbiamo seguito: contiene i dati pubblicati per un'istanza specifica del widget.
Nell'esempio del widget di testo, vedrai anche alcune interessanti funzionalità di sicurezza che potresti voler esaminare un po 'di più quando sviluppi i tuoi widget. Per questo tutorial, tuttavia, è sufficiente vedere il contenuto delle variabili $ titolo
e $ testo
vengono letti dall'array pubblicato e quindi archiviati come una matrice alle opzioni del widget sulla riga 6.
Se ti stai chiedendo il compatto()
funzione, è l'opposto di estratto()
, e prende le variabili locali i cui nomi sono stati passati come parametri e li trasforma in una matrice con i nomi come chiavi.
Finalmente il nuovo $ options
array è memorizzato come dati per il widget, widget_many
nel codice di esempio o widget_text
nel widget di testo, usando il update_option ()
funzione.
L'ultima cosa che rimane nella funzione delle impostazioni del widget è il disegno del modulo per questa istanza del widget. Questo modulo non viene visualizzato sullo schermo così come è, ma WordPress lo converte in una forma reale in seguito, utilizzando alcune magie JavaScript. Il codice riportato di seguito proviene dal codice del modello, quindi viene utilizzato $ qualcosa
per rappresentare i dati del widget. Nel widget di testo viene sostituito da $ titolo
e $ testo
, e nel tuo widget con tutto ciò che devi salvare.
È importante notare che, sebbene il salvataggio sia eseguito per ogni istanza in una volta, il modulo visualizzato qui è per una sola istanza. Qui è dove utilizzeremo l'ID istanza del widget letto all'inizio della funzione.
if (-1 == $ number) $ something = "; $ number = '% i%'; else $ something = attribute_escape ($ options [$ number] ['something']);
Nelle righe precedenti, il widget controlla innanzitutto se è stato fornito o meno un numero di widget valido. In caso contrario, e numero di $
è stato impostato sul valore predefinito, -1, tutti i dati devono essere impostati su valori predefiniti. Altrimenti, otterremo i dati dal $ options
array e usarlo per compilare il modulo con le impostazioni correnti. Questa è una buona cosa da fare in modo che l'utente non debba sempre iniziare a modificare il widget da una lavagna vuota.
E poi, il modulo stesso è costruito in modo che possa essere letto in una matrice quando inviato al codice di gestione del widget: gli input del modulo sono nominati seguendo lo schema widget di-molti [numero $] [qualcosa]
dove numero di $
è il numero di questa istanza di widget e qualcosa
è il nome del parametro da salvare. WordPress quindi analizza questo nella struttura di array descritta in precedenza quando l'utente invia il modulo.
Il modulo non ha un pulsante di invio perché tutti i widget vengono salvati utilizzando lo stesso pulsante di invio fornito da WordPress.
Perché WordPress mostri un widget nell'elenco dei widget, devi registrarlo dicendo a WordPress quali funzioni utilizzare per rendere il widget e le sue impostazioni. Il modo in cui questo viene fatto per i multi-widget non è diverso dai normali widget. L'unica differenza sta nel modo in cui è definito l'id del widget: In $ control_ops
(riga 7), diciamo a WordPress di abilitare più istanze e allegare tutte le istanze del widget con un id che inizia "molti"
a questo tipo di widget.
function widget_many_register () if (! $ options = get_option ('widget_many')) $ options = array (); $ widget_ops = array ('classname' => 'widget_many', 'description' => __ ('Widget che consente più istanze')); $ control_ops = array ('width' => 400, 'height' => 350, 'id_base' => 'many'); $ name = __ ('Many'); $ registrati = falso; foreach (array_keys ($ options) as $ o) // I vecchi widget possono avere valori nulli per qualche motivo se (! isset ($ options [$ o] ['something'])) continua; // $ id dovrebbe apparire come $ id_base - $ o $ id = "many- $ o"; // Non tradurre mai mai un ID $ registrato = true; wp_register_sidebar_widget ($ id, $ name, 'widget_many', $ widget_ops, array ('numero' => $ o)); wp_register_widget_control ($ id, $ name, 'widget_many_control', $ control_ops, array ('numero' => $ o)); // Se non ce ne sono, registriamo // l'esistenza del widget con un modello generico se (! $ Registrato) wp_register_sidebar_widget ('many-1', $ name, 'widget_many', $ widget_ops, array ('numero' = > -1)); wp_register_widget_control ('many-1', $ name, 'widget_many_control', $ control_ops, array ('numero' => -1)); // Questo è importante add_action ('widgets_init', 'widget_many_register');
Nella funzione sopra, prima registriamo tutti i widget esistenti di questo tipo, saltando quelli che non hanno dati validi (righe 11-23), e poi se non ci sono ancora istanze disponibili, registrane uno predefinito per assicurarti il widget è registrato e disponibile nella barra laterale (righe 27-32).
Come ultimo, passaggio cruciale, sulla linea 34, agganciamo la funzione di inizializzazione del widget al widgets_init
evento in modo che WordPress lo chiamerà quando è il momento di inizializzare tutti i widget. Senza questa funzione, non vedremmo nessuna delle funzionalità del widget che abbiamo appena analizzato visto che nessuna parte del codice verrà mai chiamata.
Nei frammenti sopra, ho deliberatamente omesso parte del codice per rendere le cose più leggibili, quindi non sarà possibile copiare semplicemente i pezzi e metterli insieme. Invece, dovresti andare a copiare lo stesso codice dall'installazione di WordPress.
Dopodiché, devi solo inserire le tue funzionalità e ce l'hai: il tuo multi-widget.