Codex WordPress: cosa sono gli hook e come utilizzarli

Cosa sono gli hook di filtro e d’azione Gli sviluppatori che hanno necessità di personalizzare il funzionamento di WordPress non possono mettere mano al codice sorgente di WordPress (il “Core”), perché le loro modifiche verrebbero sovrascritte dal rilascio della versione successiva. Per ovviare a questo problema, nel Core sono disseminati gli hook, ovvero dei punti […]

Photo by Ilya Pavlov on Unsplash

immagine dell'autore dell'articolo

Scritto da: Alberto

Una vita nell'informatica, per lavoro e per passione.
agsdix-far fa-calendar-alt
Data pubblicazione: 10 Agosto 2021
Categorie: Codex
agsdix-far fa-comments

Cosa sono gli hook di filtro e d’azione

Gli sviluppatori che hanno necessità di personalizzare il funzionamento di WordPress non possono mettere mano al codice sorgente di WordPress (il “Core”), perché le loro modifiche verrebbero sovrascritte dal rilascio della versione successiva.

Per ovviare a questo problema, nel Core sono disseminati gli hook, ovvero dei punti in cui gli sviluppatori possono inserire le proprie istruzioni, per personalizzare il comportamento di WordPress.

Quando WordPress è in esecuzione e incontra un hook:

  • interrompe il proprio funzionamento,
  • vede se esiste del codice personalizzato associato all’hook,
  • se esiste, lo esegue,
  • quindi riprende da dove si era interrotto.

Ci sono due tipi di hook, ciascuno con un fine specifico: i filtri e le azioni:

  • Il concetto di filtro è mutuato dai filtri cromatici del mondo della fotografia, che lasciano passare solo alcune gamme di colore, bloccando le altre. In WordPress, il filtro è una funzione che permette di modificare il valore del parametro passato in ingresso e restituirlo (con la propria aggiunta o sottrazione) al flusso principale di WordPress;
  • un hook di azione permette invece allo sviluppatore di “fare” qualcosa, come ad esempio inserire del codice HTML nella pagina in preparazione.

Non c’è rosa senza spine

Gli hook costituiscono uno strumento molto potente in mano agli sviluppatori, ma c’è un punto dolente: poiché gli hook disseminati nel Core sono molte centinaia, e a questi si aggiungono gli hook presenti nei temi e nei plugin, per lo sviluppatore non è semplice individuare l’hook da utilizzare (sempre che ce ne sia uno) per introdurre una specifica personalizzazione.

Diciamo che, una volta compreso il funzionamento degli hook, trovare quello adatto alle proprie necessità costituisce, soprattutto all’inizio, il vero problema dello sviluppatore. Ma andiamo per gradi e vediamo innanzitutto di approfondire come funzionano gli hook.

Un esempio pratico: aggiungere una nuova colonna nella pagina di elenco degli articoli

Per capire a fondo cosa sono gli hook di WordPress, utilizziamo un esempio pratico: modificare la pagina di elenco degli articoli, introducendo una nuova colonna, contenente l’ID dell’articolo.

In pratica, si tratta di passare da così:

Pagina Articoli di WordPress
fig.1 – Pagina Articoli di WordPress

a così:

Pagina Articoli di WordPress con la nuova colonna ID a destra
fig.2 – Pagina Articoli di WordPress con la nuova colonna ID a destra

La classe PHP di WordPress che si occupa della predisposizione dell’elenco degli articoli (in inglese: "post") è: \wp-admin\includes\class-wp-posts-list-table.php. Al suo interno sono presenti 18 filtri e 7 azioni. I due hook che verranno utilizzati nell’esempio sono, non a caso, un filtro e un’azione:

  • il filtro ‘manage_posts_columns‘ interviene quando viene predisposto l’elenco delle colonne da visualizzare. Questo filtro verrà utilizzato per aggiungere all’elenco la nuova colonna ID.
  • l’azione ‘manage_posts_custom_column‘ interviene in fase di visualizzazione delle righe e verrà utilizzata per dire a WordPress quale dato visualizzare all’interno della nuova colonna ID.

Come funziona un hook di filtro

Un filtro viene inserito nel codice WordPress tramite la funzione apply_filter(), che ha la seguente struttura:

apply_filters( string $hook_name, mixed $value )

dove:

  • $hook_name è il nome del filtro (‘manage_posts_columns‘ nel nostro esempio),
  • $value è il valore da filtrare, nell’esempio sarà l’array associativo $post_columns, contenente l’elenco delle colonne da visualizzare,
  • seguono eventuali parametri aggiuntivi, da utilizzare nell’applicazione del filtro.

Ecco come appare l’hook dell’esempio, in cui viene utilizzato il parametro aggiuntivo $post_type, con l’indicazione del tipo di post (utile nel caso si vogliano gestire tipi di post personalizzati):

$posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type );

Questa riga di codice non va modificata, essa offre “l’aggancio” a cui associare il vero codice personalizzato tramite la funzione add_filter(), che ha la seguente struttura:

add_filter( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 )

dove:

  • $hook_name è il nome del filtro (‘manage_posts_columns‘ nel nostro esempio),
  • $callback è il nome della funzione con il codice da eseguire,
  • $priority indica in che ordine eseguire le diverse funzioni collegate all’hook; più è bassa la priorità, prima viene eseguita la funzione,
  • $accepted_args indica il numero di parametri in ingresso alla funzione $callback, ovvero quanti parametri verranno passati dalla funzione apply_filter().

La funzione dev’essere inserita nel file functions.php del proprio tema child (o nel plugin se si sta sviluppando un plugin per WordPress).

Ed ecco il codice personalizzato da utilizzare:

add_filter( 'manage_posts_columns', 'aggiungi_id', 5, 2 ); 
function aggiungi_id( $columns, $post_type ) {
    $columns['myId'] = 'ID';
    return $columns;
}

I parametri della funzione add_filter() indicano:

  • 'manage_posts_columns': a quale hook va agganciato il nostro codice personalizzato,
  • 'aggiungi_id': il nome della funzione da aggiungere all’hook,
  • 5: la priorità con cui va eseguita la funzione aggiungi_id(), rispetto alle altre funzioni associate allo stesso hook,
  • 2: il numero di parametri in input gestiti dalla funzione aggiungi_id(),

La funzione aggiungi_id() aggiunge un nuovo elemento in coda all’array associativo $columns, quindi restituisce l’array modificato. Il parametro $post_type non viene utilizzato.

In sintesi

  • l’array associativo $columns contiene l’elenco delle colonne da visualizzare nella pagina di elenco degli articoli;
  • Con la funzione aggiungi_id() aggiungiamo una voce all’array $columns, indicando ‘ID’ come header della nuova colonna (dato che la nuova voce è in coda all’array, la colonna ID sarà l’ultima a destra).
  • Con la funzione add_filter() diciamo a WordPress in quale momento dev’essere eseguita la funzione aggiungi_id(), ovvero nell’hook 'manage_posts_columns'
  • Con la funzione apply_filter() WordPress manda in esecuzione la funzione aggiungi_id() e tutte le eventuali altri funzioni collegate allo stesso hook, rispettando le $priority indicate.

Abbiamo quindi istruito WordPress affinché presenti una colonna in più nella pagina, colonna che avrà come header “ID”. Dobbiamo ora indicare cosa visualizzare all’interno di questa colonna.

Come funziona un hook di azione

Un hook di azione viene inserito nel codice WordPress tramite la funzione do_action() che ha la seguente struttura:

do_action( string $hook_name, mixed $arg )

dove:

  • $hook_name è il nome dell’hook di azione (‘manage_posts_custom_column‘ nel nostro esempio),
  • $arg indica uno o più parametri da passare alla funzione personalizzata.

Ecco come appare l’hook dell’esempio,

do_action( 'manage_posts_custom_column', $column_name, $post->ID );

La funzione do_action() esegue tutte le funzioni personalizzate associate all’hook ‘manage_posts_custom_column’, alle quali passa: il nome della colonna $colum_name e l’ID dell’articolo $post->ID .

Il codice personalizzato viene associato all’hook tramite la funzione add_action(), che ha la seguente struttura:

add_action( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 )

I parametri hanno lo stesso significato di quelli della funzione add_filter().

La funzione dev’essere inserita nel file functions.php del proprio tema child (o nel plugin se si sta sviluppando un plugin per WordPress).

Ed ecco il codice personalizzato da utilizzare:

add_action( 'manage_posts_custom_column', 'visualizza_id', 5, 2 );
function visualizza_id( $column, $id ) {
    if( $column === 'myId' ) {
          echo $id;
    }
}

La funzione add_action() dice a WordPress: quando incontri l’hook ‘manage_posts_custom_column’ richiama la funzione con nome ‘visualizza_id’ ed eseguila con priorità 5, passandole 2 parametri.

La funzione visualizza_id() esamina il nome della colonna ricevuta come parametro e, nel caso sia 'myId', esegue un’istruzione echo del parametro $id (ovvero il $post->ID, ricevuto dalla funzione do_action(), corrispondente all’ID dell’articolo).

In sintesi

  • La funzione visualizza_id() stampa l’ID dell’articolo nella colonna ‘myId’.
  • Con la funzione add_action() diciamo a WordPress in quale momento dev’essere eseguita la funzione visualizza_id(), ovvero nell’hook 'manage_posts_custom_column'
  • Con la funzione do_action() WordPress manda in esecuzione la funzione visualizza_id() e tutte le eventuali altri funzioni collegate allo stesso hook, rispettando le $priority indicate.

Non ci rimane che mandare in esecuzione il codice e verificare come viene modificata la pagina di elenco degli articoli.

Spingiamoci oltre

Visualizzare l’ID anche nell’elenco delle pagine WordPress

E se, già che ci siamo, volessimo inserire l’ID anche nella pagina di elenco delle pagine WordPress?

Le funzioni aggiungi_id() e visualizza_id() possono essere riutilizzate, bisognerà però istruire WordPress di mandarle in esecuzione anche quando visualizza l’elenco delle pagine WordPress, per fare ciò basterà utilizzare gli hook appropriati:

add_filter( 'manage_pages_columns', 'aggiungi_id', 5, 2 );
add_action( 'manage_pages_custom_column', 'visualizza_id', 5, 2 );

Tutte le pagine di lista (Categorie, Tag, Commenti, Progetti, Prodotti di WooCommerce, ecc.) hanno specifici hook, che possono essere utilizzati per aggiungere (o togliere) colonne personalizzate.

Inserire l’ID nella posizione desiderata, invece che come ultima colonna

Volendo migliorare l’aspetto della pagina Articoli, si potrebbe desiderare di inserire la nuova colonna ID non come ultima colonna a destra, ma in una posizione a piacere, ad esempio prima del Titolo dell’articolo:

Pagina Articoli di WordPress con la nuova colonna ID a sinistra
fig.3 – Pagina Articoli di WordPress con la nuova colonna ID a sinistra

Poiché la posizione della colonna nella pagina dipende dalla posizione all’interno dell’array $columns, si deve modificare la funzione aggiungi_id() in questo modo:

function aggiungi_id( $columns, $post_type ) {
  //$columns['myId'] = 'ID';

    $myColumn = array('myId' => 'ID');
    $posizione =  1; 	/*la posizione arbitraria in cui deve comparire l'ID*/
    $columns = array_merge(
        array_slice($columns, 0, $posizione), /* prendo l'array fino alla posizione $posizione */
        $myColumn,                            /* inserisco la nuova colonna */
        array_slice($columns, $posizione)     /* aggiungo la parte rimanente dell'array originale */
    );
    return $columns;
}

Restringere l’ampiezza della colonna ID

Sempre al fine di migliorare l’aspetto della pagina, si potrebbe ridimensionare l’ampiezza della colonna ID, per lasciare maggior spazio alle altre colonne:

Pagina Articoli di WordPress con la nuova colonna ID a sinistra e ristretta
fig.4 – Pagina Articoli di WordPress con la nuova colonna ID a sinistra e ristretta

Pe ottenere questo risultato è sufficiente impostare sulla colonna la proprietà CSS width (ad es. width:40px).

Se si esamina il codice HTML della pagina Articoli di WordPress, si vede che ciascuna colonna è associata ad una classe column-idcolonna (nel nostro caso: column-myId).

Codice HTML della pagina Articoli di WordPress
fig.5 – Codice HTML della pagina Articoli di WordPress

La proprietà width potrà quindi essere associata al selettore th.column-myId:

th.column-myId {
    width: 40px;
}

Questa regola CSS non può però essere inserita nel file style.css del tema figlio, in quanto stiamo lavorando su una pagina di back-end. Si dovrà quindi inserire la regola in uno stylesheet caricato da WordPress durante la visualizzazione delle pagine “admin”.

Per far ciò si può utilizzare l’hook di azione admin_enqueue_scripts.

Inoltre, invece che creare ed accodare un nuovo file .css contenente un’unica regola, si andrà ad inserire direttamente nell’HTML della pagina un elemento <style> con la regola in questione:

function aggiungi_le_mie_regole_css() {
?>
    <style type="text/css">
        th.column-myId {
            width: 40px;
        }
    </style>
<?php        
}
add_action( 'admin_enqueue_scripts', 'aggiungi_le_mie_regole_css' );

Come individuare gli hook utilizzati per la preparazione di una pagina WordPress

Come accennato in precedenza, trovare l’hook adatto alle proprie necessità costituisce, soprattutto all’inizio, il vero problema dello sviluppatore.

Esistono dei plugin che possono essere d’aiuto:

  • il plugin Query Monitor che, tra le numerose funzioni messe a disposizione dello sviluppatore, offre anche l’elenco degli hook utilizzati da WordPress nella creazione di una determinata pagina;
  • il plugin Show Hook che, come dice il nome, è finalizzato ad esporre tutti gli hook su cui WordPress è transitato (e quindi non solo quelli effettivamente utilizzati) nella creazione di una pagina.

Risorse online

0 commenti

Invia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *