Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

⚙️ WordPress: come impostare un template predefinito per un custom post type

⚙️ 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}.php nella root del tema e WordPress lo caricherà automaticamente seguendo la gerarchia dei template
  • Agganciati al filtro template_include nel functions.php per assegnare un template in modo programmatico senza inserire un file fisico nel tema
  • Per i temi a blocchi, crea single-{post_type}.html nella cartella templates/; 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.phpsingle.phpsingular.phpindex.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
3add_filter( 'template_include', 'sd_cpt_default_template', 99 );
4
5function 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 tipo portfolio
  • 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:

1add_filter( 'single_template', 'sd_cpt_template_by_type' );
2
3function 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: single-{post_type}.php

Plugin con un proprio template

Metodo 2: template_include

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: templates/single-{post_type}.html

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 controlla in_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 sul body. Aggiungi un filtro body_class nel functions.php in modo che WordPress applichi una classe post-type-{slug} al <body> e gli stili si attiveranno:

1add_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.php resta 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 standard post e page:

1add_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.