Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

🛠 Tassonomie esclusive in WordPress: come sostituire le caselle di controllo con pulsanti radio

🛠 Tassonomie esclusive in WordPress: come sostituire le caselle di controllo con pulsanti radio

Di default, WordPress ti permette di assegnare a un articolo tutti i termini di una stessa tassonomia che desideri. Caselle di spunta nella barra laterale e il gioco è fatto. Ma cosa succede se il cliente ha bisogno che l'editor selezioni esattamente un'opzione? Per esempio, «Tipo di progetto»: case study, landing page o negozio online. Tre opzioni, e averne due insieme non ha senso.

Non esiste un interruttore nativo «rendi la tassonomia esclusiva» in WordPress. Un ticket su Trac è fermo dal 2010 senza progressi. Ma il compito si può risolvere con il codice, senza plugin né dipendenze esterne.

Alla fine di questo articolo avrai trasformato il meta box standard con le caselle di spunta in un pannello con pulsanti radio: esattamente un termine per articolo, meno errori dell'editor.

💡 Panoramica rapida:

  • Registra una tassonomia con il parametro meta_box_cb in modo che il meta box standard non compaia.
  • Sull'hook add_meta_boxes, crea il tuo blocco con i pulsanti radio.
  • Usa save_post per scrivere il termine selezionato nel database.
  • Il codice completo può essere copiato nel functions.php del tema child e funziona immediatamente.

Cosa sono le tassonomie e perché l'esclusività è importante

Una tassonomia in WordPress è un meccanismo per raggruppare gli articoli. Anche le «Categorie» e i «Tag» standard sono tassonomie. Una tassonomia personalizzata si crea per un compito specifico: «Tipo di progetto» per un portfolio, «Regione» per una directory di filiali, «Tipo di servizio» per un listino prezzi.

Le categorie integrate funzionano come una tassonomia esclusiva: un articolo appartiene esattamente a una categoria, a meno che non si usino plugin di estensione. La gerarchia «genitore → figlio» suggerisce all'editor la logica di selezione.

Tuttavia, qualsiasi tassonomia personalizzata registrata tramite register_taxonomy() è non esclusiva di default. L'interfaccia è composta da caselle di spunta o da un campo con completamento automatico. Per i tag e gli attributi di prodotto, questo è corretto. Ma quando ogni articolo deve avere esattamente un termine, le caselle di spunta diventano una fonte di errori.

La soluzione: nascondere il meta box standard e renderizzarne uno proprio, con pulsanti radio e controllo rigoroso. Non è un espediente, ma un'API documentata di WordPress, solo distribuita su diversi passaggi.

Passaggio 1: registrare una tassonomia personalizzata

La base è la funzione register_taxonomy(). Il codice si aggiunge al functions.php del tema child o tramite il plugin Code Snippets. Creiamo una tassonomia project_type per gli articoli standard:

1function sd_register_project_type_taxonomy() {
2 register_taxonomy(
3 'project_type',
4 'post',
5 array(
6 'label' => __( 'Project Type', 'textdomain' ),
7 'public' => true,
8 'show_in_rest' => true,
9 'hierarchical' => true,
10 'show_in_quick_edit' => false,
11 'meta_box_cb' => false,
12 )
13 );
14}
15add_action( 'init', 'sd_register_project_type_taxonomy' );

Parametri chiave:

  • hierarchical => true abilita una struttura ad albero, come le categorie. I termini sono organizzati gerarchicamente: «Design → Landing page», «Sviluppo → Negozio online».
  • show_in_rest => true rende la tassonomia disponibile nell'API REST e nell'editor a blocchi. Senza questo, Gutenberg non vedrà il meta box.
  • meta_box_cb => false e show_in_quick_edit => false rimuovono completamente l'interfaccia standard di selezione dei termini.

Dopo aver salvato il codice, la tassonomia project_type è comparsa nel menu «Articoli». I termini si aggiungono tramite «Articoli → Tipo di progetto» con un'interfaccia standard, come per le categorie.

Passaggio 2: nascondere il meta box standard

Questo passaggio in realtà è già stato fatto con i parametri meta_box_cb e show_in_quick_edit nel passaggio 1. Per ricapitolare:

  • meta_box_cb => false rimuove il meta box dalla pagina di modifica dell'articolo.
  • show_in_quick_edit => false nasconde la tassonomia dai pannelli di modifica rapida e modifica in blocco.

Senza di essi, WordPress aggiunge un'interfaccia predefinita: per le tassonomie gerarchiche, le caselle di spunta delle categorie; per quelle non gerarchiche, un campo tag con completamento automatico.

Parametri meta_box_cb e show_in_quick_edit in register_taxonomy

I termini vengono popolati tramite una pagina di gestione separata:

Pagina di gestione dei termini di una tassonomia personalizzata nell'amministrazione di WordPress

Passaggio 3: creare un meta box personalizzato con pulsanti radio

Registra il tuo meta box tramite l'hook add_meta_boxes. Aggiungi al functions.php:

1add_action( 'add_meta_boxes', 'sd_add_project_type_meta_box' );
2
3function sd_add_project_type_meta_box() {
4 add_meta_box(
5 'project_type_box',
6 __( 'Project Type', 'textdomain' ),
7 'sd_render_project_type_meta_box',
8 'post',
9 'side',
10 'default'
11 );
12}

Parametri di add_meta_box():

  • project_type_box: ID interno (arbitrario ma univoco).
  • 'Project Type': titolo nel pannello di amministrazione.
  • sd_render_project_type_meta_box: funzione di rendering.
  • 'post': tipo di articolo; può essere un array per più CPT.
  • 'side': barra laterale. Alternative: 'normal', 'advanced'.

La funzione che renderizza i pulsanti radio:

1function sd_render_project_type_meta_box( $post ) {
2 $terms = get_terms( array(
3 'taxonomy' => 'project_type',
4 'hide_empty' => false,
5 ) );
6
7 if ( empty( $terms ) || is_wp_error( $terms ) ) {
8 echo '<p>First, add terms on the “Project Type” page.</p>';
9 return;
10 }
11
12 $current_terms = get_the_terms( $post->ID, 'project_type' );
13 $current_id = ( ! empty( $current_terms ) && ! is_wp_error( $current_terms ) )
14 ? $current_terms[0]->term_id
15 : 0;
16
17 foreach ( $terms as $term ) : ?>
18 <label style="display:block;margin-bottom:4px;">
19 <input type="radio"
20 name="project_type_term"
21 value="<?php echo esc_attr( $term->term_id ); ?>"
22 <?php checked( $current_id, $term->term_id ); ?>>
23 <?php echo esc_html( $term->name ); ?>
24 </label>
25 <?php endforeach;
26}

Cosa è importante qui:

  • get_terms() con hide_empty => false restituisce tutti i termini, inclusi quelli non utilizzati.
  • get_the_terms() restituisce un array; prendiamo il primo elemento [0] poiché la logica garantisce non più di un termine.
  • checked() è una funzione integrata di WordPress che produce checked="checked" quando c'è corrispondenza.
  • esc_attr() e esc_html() sono escaping obbligatori.

Il risultato è un blocco pulito con pulsanti radio:

Metabox personalizzato con pulsanti di opzione per selezionare un singolo termine della tassonomia

Niente caselle di spunta, nessun modo per selezionare due opzioni.

Passaggio 4: salvare il termine quando l'articolo viene salvato

Senza questo passaggio, il meta box è puramente decorativo. Usiamo l'hook save_post:

1add_action( 'save_post', 'sd_save_project_type_term' );
2
3function sd_save_project_type_term( $post_id ) {
4 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
5 return;
6 }
7
8 if ( ! current_user_can( 'edit_post', $post_id ) ) {
9 return;
10 }
11
12 if ( isset( $_POST['project_type_term'] ) ) {
13 $term_id = absint( $_POST['project_type_term'] );
14 wp_set_object_terms( $post_id, $term_id, 'project_type' );
15 }
16}

Dettagli:

  • DOING_AUTOSAVE: saltiamo i salvataggi automatici. Senza questo controllo, il termine viene sovrascritto in background ogni 60 secondi.
  • current_user_can( 'edit_post', $post_id ): controllo di base dei permessi.
  • absint() converte il valore in un intero positivo, più sicuro di (int) sanitize_text_field().
  • wp_set_object_terms() con un ID singolo (non un array) scrive esattamente un termine, rimuovendo le associazioni precedenti.

Fatto. Salva l'articolo e la selezione del pulsante radio sarà fissata. Quando lo riapri, il termine selezionato è evidenziato.

Codice completo da copiare

Tutti e quattro i passaggi in un unico snippet. Aggiungi al functions.php del tuo tema child o tramite Code Snippets:

1/**
2 * Exclusive taxonomy "Project Type" — one term per post.
3 * Add to child theme's functions.php.
4 */
5function sd_register_project_type_taxonomy() {
6 register_taxonomy(
7 'project_type',
8 'post',
9 array(
10 'label' => __( 'Project Type', 'textdomain' ),
11 'public' => true,
12 'show_in_rest' => true,
13 'hierarchical' => true,
14 'show_in_quick_edit' => false,
15 'meta_box_cb' => false,
16 )
17 );
18}
19add_action( 'init', 'sd_register_project_type_taxonomy' );
20
21add_action( 'add_meta_boxes', 'sd_add_project_type_meta_box' );
22
23function sd_add_project_type_meta_box() {
24 add_meta_box(
25 'project_type_box',
26 __( 'Project Type', 'textdomain' ),
27 'sd_render_project_type_meta_box',
28 'post',
29 'side',
30 'default'
31 );
32}
33
34function sd_render_project_type_meta_box( $post ) {
35 $terms = get_terms( array(
36 'taxonomy' => 'project_type',
37 'hide_empty' => false,
38 ) );
39
40 if ( empty( $terms ) || is_wp_error( $terms ) ) {
41 echo '<p>First, add terms on the “Project Type” page.</p>';
42 return;
43 }
44
45 $current_terms = get_the_terms( $post->ID, 'project_type' );
46 $current_id = ( ! empty( $current_terms ) && ! is_wp_error( $current_terms ) )
47 ? $current_terms[0]->term_id
48 : 0;
49
50 foreach ( $terms as $term ) : ?>
51 <label style="display:block;margin-bottom:4px;">
52 <input type="radio"
53 name="project_type_term"
54 value="<?php echo esc_attr( $term->term_id ); ?>"
55 <?php checked( $current_id, $term->term_id ); ?>>
56 <?php echo esc_html( $term->name ); ?>
57 </label>
58 <?php endforeach;
59}
60
61add_action( 'save_post', 'sd_save_project_type_term' );
62
63function sd_save_project_type_term( $post_id ) {
64 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
65 return;
66 }
67
68 if ( ! current_user_can( 'edit_post', $post_id ) ) {
69 return;
70 }
71
72 if ( isset( $_POST['project_type_term'] ) ) {
73 $term_id = absint( $_POST['project_type_term'] );
74 wp_set_object_terms( $post_id, $term_id, 'project_type' );
75 }
76}

⚠️ Fai un backup completo del sito prima di incollare. Il codice è stato testato sulla versione corrente di WordPress con l'editor classico. In Gutenberg, il meta box personalizzato viene visualizzato nella barra laterale senza modifiche.

Nella pratica, abbiamo distribuito questo snippet su tre progetti e ha funzionato ovunque senza modifiche. Se hai un tipo di articolo gerarchico o più ruoli editor, sostituisci 'post' con il tuo slug e verifica i permessi in save_post.


Il Trac di WordPress ha il ticket #14877 aperto dal 2010 per il supporto nativo alla tassonomia esclusiva. Una volta che un parametro 'exclusive' => true apparirà nel core, l'intero costrutto si ridurrà a una singola riga. Finché il ticket non vedrà movimento, l'approccio con i pulsanti radio resta la soluzione principale.

E qui sotto, un breve video sull'argomento per vedere il processo in azione:

⁉️🤔 Domande frequenti

Funziona in Gutenberg?

Sì. Il parametro show_in_rest => true al momento della registrazione della tassonomia abilita la compatibilità con l'editor a blocchi. Il meta box personalizzato appare nella barra laterale del documento e i pulsanti radio vengono visualizzati e salvati correttamente.

Questo approccio si può applicare ai tipi di articolo personalizzati?

Sì. Sostituisci 'post' in register_taxonomy() e add_meta_box() con lo slug del tuo CPT. Il resto del codice (nome della tassonomia, etichetta, parametri) rimane lo stesso. L'approccio funziona con qualsiasi tipo di articolo registrato, inclusi quelli creati tramite ACF o Custom Post Type UI.

Cosa succede se l'editor non seleziona nessun termine?

L'articolo verrà salvato senza un termine assegnato; save_post semplicemente non chiamerà wp_set_object_terms(). Se la selezione obbligatoria è critica, aggiungi una validazione JavaScript nell'amministrazione o un controllo tramite l'hook pre_post_update.

Perché non usare il plugin Radio Buttons for Taxonomies?

Puoi farlo. Il plugin risolve il compito senza codice e ha oltre 100.000 installazioni attive. Lo svantaggio è un'altra dipendenza. Per uno o due siti, il plugin è giustificato. Per agenzie e multisito, il codice nel tema dà il pieno controllo senza aggiornamenti extra e conflitti.

Come aggiungo la selezione gerarchica (genitore → figlio)?

Le tassonomie gerarchiche (hierarchical => true) ottengono automaticamente una struttura genitore-figlio. Per visualizzare la gerarchia nel meta box personalizzato, sostituisci get_terms() con wp_dropdown_categories() usando il parametro 'taxonomy' => 'project_type'; la funzione produrrà un select con indentazione.

In conclusione: quando vale la pena scrivere codice

Una tassonomia esclusiva non serve per ogni progetto. Se gli editor capiscono la logica del sito e non commettono errori nella selezione, le caselle di spunta standard sono sufficienti. Ma quando il costo degli errori è alto (una landing page nel portfolio erroneamente contrassegnata sia come «negozio online» che come «case study»), mezz'ora di codifica ripaga in pulizia dei contenuti.

  • Se hai un sito e nessuno sviluppatore, installa Radio Buttons for Taxonomies. Funziona senza codice.
  • Se sei un'agenzia o gestisci un multisito, copia il codice sopra nel tuo tema base. Meno plugin, meno punti di rottura durante gli aggiornamenti.
  • Se il tuo sito gira su puro Gutenberg, valuta se hai davvero bisogno di una tassonomia. Forse un campo ACF con pulsanti radio è sufficiente: meno entità, amministrazione più veloce.

Inizia con un sito di test. Registra la tassonomia, aggiungi tre termini e crea un articolo; l'interfaccia funzionerà immediatamente. Scrivi nei commenti per quale compito hai usato una tassonomia esclusiva.