
⚙️ WordPress: come impostare un template predefinito per un custom post type
Hai consegnato al cliente un sito su WordPress con un portfolio e il giorno dopo ti richiama: «Sto aggiungendo una nuova voce, ma il template continua a tornare a quello predefinito con la sidebar. Come faccio a bloccarlo?». La situazione è dolorosamente familiare: clicchi su «Aggiungi nuovo» in un custom post type e invece del layout a tutta larghezza che hai costruito, esce una colonna da blog con la sidebar. Scegliere il template manualmente per ogni contenuto è un lavoro inutile che frustra sia te sia il cliente. Soprattutto quando «Larghezza intera» senza sidebar è ciò che serve quasi sempre.
Di default, WordPress usa single.php del tema per i custom post type (CPT). E single.php di solito è pensato per il blog: titolo, contenuto, sidebar con widget. Per portfolio, case study, testimonianze o prodotti, quel layout è poco adatto. La buona notizia: WordPress offre quattro modi per assegnare un template a un CPT, dal più semplice (un file nel tema, zero codice) a quello completamente programmatico tramite hook e temi a blocchi. Ogni metodo fa il suo lavoro in modo affidabile; l'unica differenza è il livello di controllo e la facilità di manutenzione.
💡 Panoramica rapida:
- Crea un file
single-{post_type}.phpnella root del tema e WordPress lo caricherà automaticamente seguendo la gerarchia dei template - Agganciati al filtro
template_includenelfunctions.phpper assegnare un template in modo programmatico senza inserire un file fisico nel tema - Per i temi a blocchi, crea
single-{post_type}.htmlnella cartellatemplates/; può essere modificato tramite l'Editor del sito senza toccare codice - Dopo ogni modifica, svuota i permalink: «Impostazioni → Permalink → Salva le modifiche», altrimenti WordPress non vedrà il nuovo template
Metodo 1: file di template tramite la gerarchia di WordPress
Il metodo più affidabile e diretto. Dalla versione 3.0, WordPress supporta template personalizzati per i CPT attraverso la gerarchia standard dei template. Ecco come funziona: quando un visitatore apre una voce di tipo portfolio, WordPress cerca un template in un ordine preciso, dall'alto verso il basso, e usa il primo file che trova:
single-portfolio.php → single.php → singular.php → index.php
Devi creare un file chiamato single-{post_type}.php, dove {post_type} è lo slug del tuo tipo personalizzato. Inseriscilo nella root del tema attivo:
1 /* File: /wp-content/themes/your-theme/single-portfolio.php */ 2 3 <?php get_header(); ?> 4 5 <div class="full-width-content"> 6 <?php while ( have_posts() ) : the_post(); ?> 7 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 8 <h1><?php the_title(); ?></h1> 9 <div class="entry-content"> 10 <?php the_content(); ?> 11 </div> 12 </article> 13 <?php endwhile; ?> 14 </div> 15 16 <?php get_footer(); ?> 17
Il modo più rapido per iniziare: copia il contenuto di page.php o template-fullwidth.php dal tuo tema e adatta il layout al CPT specifico. Se non esiste alcun file single-{post_type}.php, WordPress ripiega silenziosamente su single.php e il cliente si ritrova con una sidebar.
Il vantaggio di questo metodo: nessun codice nel functions.php; il file sta semplicemente nel tema e funziona. Lo svantaggio: il template è strettamente legato al tema. Se cambi tema, il file resta nella vecchia cartella e smette di funzionare.
Metodo 2: in modo programmatico tramite il filtro template_include
Il metodo basato su file funziona finché controlli il tema. Ma se stai sviluppando un plugin o un tema child che non deve dipendere dalla presenza di un file nella root, ti serve l'hook template_include.
Il filtro si attiva prima che il template venga caricato e ti permette di puntare a un file PHP da qualsiasi posizione:
1 /* File: functions.php (theme) or main plugin file */ 2 3 add_filter( 'template_include', 'sd_cpt_default_template', 99 ); 4 5 function sd_cpt_default_template( $template ) { 6 if ( is_singular( 'portfolio' ) ) { 7 $custom_template = plugin_dir_path( __FILE__ ) . 'templates/single-portfolio.php'; 8 if ( file_exists( $custom_template ) ) { 9 return $custom_template; 10 } 11 } 12 return $template; 13 }
Cosa succede qui:
is_singular('portfolio')verifica se siamo sulla pagina di una singola voce del tipoportfolio- Se la condizione è vera, WordPress carica il template dalla cartella del plugin, ignorando la gerarchia del tema
- La priorità 99 assicura che il filtro venga eseguito per ultimo e non sia sovrascritto dal tema
Questo approccio è comodo quando il template deve risiedere dentro un plugin e sopravvivere ai cambi di tema. Il file templates/single-portfolio.php dentro il plugin può usare get_header() e get_footer() del tema attivo, quindi visivamente tutto resta coerente con il design del sito.
Metodo 3: il filtro {$type}_template
WordPress mette a disposizione un hook dinamico {$type}_template, dove $type è single, archive o page. Per un CPT assume la forma single-portfolio_template e ti permette di sovrascrivere il template in modo preciso, senza controlli aggiuntivi dentro la callback:
1 add_filter( 'single_template', 'sd_cpt_template_by_type' ); 2 3 function sd_cpt_template_by_type( $single_template ) { 4 global $post; 5 6 if ( 'portfolio' === $post->post_type ) { 7 $custom_template = get_stylesheet_directory() . '/single-portfolio.php'; 8 if ( file_exists( $custom_template ) ) { 9 return $custom_template; 10 } 11 } 12 return $single_template; 13 }
La differenza rispetto al Metodo 2 è semantica: stai dicendo esplicitamente «cambia il template per le voci singole» invece di «intercetta tutti i template». Il codice è leggermente più pulito, ma a livello funzionale entrambi gli hook risolvono il problema allo stesso modo.
Metodo 4: template in un tema a blocchi (Full Site Editing)
A partire da WordPress 5.9 e con il passaggio ai temi a blocchi, l'approccio cambia. Nei temi FSE, i template sono file HTML nella cartella templates/, non PHP. Per un custom post type, crea:
1 /wp-content/themes/your-fse-theme/templates/single-portfolio.html
All'interno, usi una struttura basata su blocchi. Un esempio minimo:
1 <!-- wp:template-part {"slug":"header","theme":"your-fse-theme"} /--> 2 3 <!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} --> 4 <main class="wp-block-group"> 5 <!-- wp:post-title {"level":1} /--> 6 <!-- wp:post-featured-image /--> 7 <!-- wp:post-content {"layout":{"type":"constrained"}} /--> 8 </main> 9 <!-- /wp:group --> 10 11 <!-- wp:template-part {"slug":"footer","theme":"your-fse-theme"} /-->
Puoi modificare questo template direttamente nell'Editor del sito (Aspetto → Editor) senza toccare codice. Se cambi tema a blocchi, il file resta nella vecchia cartella, la stessa vulnerabilità del Metodo 1.
Quale metodo scegliere
Una matrice decisionale rapida per il tuo scenario:
Scenario | Metodo |
|---|---|
Un tema, un CPT, nessun plugin | Metodo 1: |
Plugin con un proprio template | Metodo 2: |
Tema child, necessità di sovrascrivere il template del tema padre | Metodo 1 o 3 |
FSE / tema a blocchi (Twenty Twenty-Four e successivi) | Metodo 4: |
Dopo aver implementato uno qualsiasi dei metodi, ricordati di andare su «Impostazioni → Permalink» e cliccare «Salva le modifiche». Questo svuota la cache delle regole di riscrittura e WordPress inizia a riconoscere il nuovo template.
⁉️🤔 Domande frequenti
Il template non viene caricato. Cosa devo fare?
Per prima cosa, svuota i permalink («Impostazioni → Permalink → Salva»). In secondo luogo, verifica che lo slug del CPT nel nome del file corrisponda allo slug di
register_post_type(). In terzo luogo, se è attivo un plugin di caching, svuota la cache. Nella pratica, il problema è quasi sempre legato allo svuotamento delle regole di riscrittura dopo la registrazione del CPT, non al codice del template in sé.
Posso assegnare un template a più CPT contemporaneamente?
Sì. Nel Metodo 2, usa un array in
is_singular():is_singular( array( 'portfolio', 'testimonials', 'team' ) ). Oppure controllain_array( $post->post_type, array('portfolio', 'team') )dentro la callback. Il file del template è uno solo e il layout sarà condiviso tra tutti i tipi elencati.
Il template funziona, ma il layout è rotto (mancano gli stili della sidebar/dell'header).
Hai ereditato il template da
page.php, ma gli stili del tema dipendono dalle classi CSS sulbody. Aggiungi un filtrobody_classnelfunctions.phpin modo che WordPress applichi una classepost-type-{slug}al<body>e gli stili si attiveranno:
1 add_filter( 'body_class', function( $classes ) { 2 if ( is_singular( 'portfolio' ) ) { 3 $classes[] = 'single-portfolio'; 4 } 5 return $classes; 6 } );
Cosa succede quando cambio tema? Il template sparisce.
Sì, il file
single-portfolio.phpresta nella cartella del vecchio tema. Le tue opzioni: sposta il file manualmente nel nuovo tema, usa un tema child (il file sopravvive agli aggiornamenti del tema padre) oppure sposta il template in un plugin tramite il Metodo 2, che non dipende dal tema attivo.
E se avessi bisogno che TUTTI i CPT si aprano senza sidebar di default?
Usa un filtro universale con
is_singular()senza specificare un post_type particolare, ma escludi i tipi standardpostepage:
1 add_filter( 'template_include', function( $template ) { 2 if ( is_singular() && ! is_singular( array( 'post', 'page' ) ) ) { 3 $fullwidth = get_stylesheet_directory() . '/template-fullwidth.php'; 4 if ( file_exists( $fullwidth ) ) { 5 return $fullwidth; 6 } 7 } 8 return $template; 9 }, 99 );
Questa soluzione applica un unico template a tutta larghezza a tutti i custom post type in una volta sola: portfolio, testimonianze, membri del team, case study. I post e le pagine standard non vengono toccati.
Vale la pena usare template_include quando puoi semplicemente creare un file?
Se hai un sito, un tema e un CPT, crea single-{post_type}.php e dimenticatene. Questa è una soluzione che dura anni: non si rompe con gli aggiornamenti di WordPress, non dipende dalla versione PHP ed è immediatamente chiara a qualsiasi sviluppatore apra la cartella del tema. La manutenzione si riduce a un singolo file che sistemi in un attimo.
I metodi programmatici tramite hook sono giustificati in due casi. Primo: il template fa parte di un plugin distribuito e non vuoi obbligare gli utenti a copiare file nel tema. Secondo: i CPT sono registrati dinamicamente tramite ACF, Toolset o un plugin simile, e far proliferare una dozzina di file single-*.php nel tema è poco pratico. Per tutto il resto, la gerarchia dei template di WordPress è il percorso più semplice e affidabile, collaudato negli anni.



