Come visualizzare lo stesso custom post type su 2 template single diversi
Ho un cliente che vuole visualizzare i piani casa (un custom post type) sul suo sito in due sezioni con branding diverso, a seconda della pagina di elenco da cui si accede al post. Ho trovato questa soluzione di @gmazzap di qualche anno fa, che sembra promettente, ma non riesco a farla funzionare: Multiple templates for custom post type
Nello specifico, non riesce a modificare l'URL sulla pagina di elenco alternativa: utilizza semplicemente lo slug specificato nella registrazione del CPT:
'rewrite' => array( 'slug' => 'plan', 'with_front' => false ),
Ciò significa che quando clicco su un link del piano nel template 'page_kioskoverview.php', il post viene visualizzato sul template standard 'single-plans.php' anziché su quello alternativo 'single-kioskplans.php'.
Ecco come appare il mio codice:
add_action('template_redirect', 'change_plans_plink');
function change_plans_plink() {
if (is_page_template('page_kioskoverview.php')) {
add_filter( 'post_link', 'plans_query_string', 10, 2 );
}
}
function plans_query_string( $url, $post ) {
if ( $post->post_type === 'plans' ) {
$url = add_query_arg( array('style'=>'alt'), $url );
}
return $url;
}
// designa un template single alternativo per il link alt sopra
add_action('template_include', 'kiosk_plan_single');
function kiosk_plan_single($template) {
if( is_singular('plans') ) {
$alt = filter_input(INPUT_GET, 'style', FILTER_SANITIZE_STRING);
if ( $alt === 'alt' ) $template = 'single-kioskplans.php';
}
return $template;
}
Dopo alcuni giorni passati a guardarlo (e aver provato alcune varianti senza successo), non riesco a individuare il problema, ma devo aver trascurato qualcosa.

Per visualizzare template diversi per lo stesso tipo di post creerei 2 link differenti, verificherei su quale link mi trovo attualmente e deciderei quale template caricare.
Esempio funzionante:
/**
* Registra il post type per gli eventi
*
* La registrazione del post type eventi aggiungerà una struttura di permalink come event/([^/]+)/?$
*/
function wpse_288345_register_event_post_type() {
$labels = array(
'name' => __( 'Eventi' ),
'singular_name' => __( 'Evento' ),
'add_new' => __( 'Aggiungi nuovo' ),
'add_new_item' => __( 'Aggiungi nuovo' ),
'edit_item' => __( 'Modifica' ),
'new_item' => __( 'Nuovo' ),
'view_item' => __( 'Visualizza' ),
'search_items' => __( 'Cerca' ),
'not_found' => __( 'Non trovato' ),
'not_found_in_trash' => __( 'Nessun Evento trovato nel cestino' ),
'parent_item_colon' => __( 'Genitore' ),
'menu_name' => __( 'Eventi' ),
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'supports' => array( 'title', 'page-attributes' ),
'taxonomies' => array(),
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => false,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => array('slug' => 'event'),
'capability_type' => 'post',
);
register_post_type( 'event', $args );
}
add_action( 'init', 'wpse_288345_register_event_post_type' );
/**
* Aggiunge regole di rewrite personalizzate per il post type eventi.
*
* Ricordati di svuotare le regole di rewrite per applicare le modifiche.
*/
function wpse_288345_add_event_rewrite_rules() {
/**
* Regole di rewrite personalizzate per un post type.
*
* Sapremo su quale url ci troviamo tramite i parametri $_GET 'performers' e 'summary'. Che aggiungeremo
* alle query vars pubbliche per ottenerli in modo conveniente.
*/
add_rewrite_rule('event/performers/([^/]+)/?$', 'index.php?post_type=event&name=$matches[1]&performers=1', 'top');
add_rewrite_rule('event/summary/([^/]+)/?$', 'index.php?post_type=event&name=$matches[1]&summary=1', 'top');
}
add_action('init', 'wpse_288345_add_event_rewrite_rules');
/**
* Aggiunge le query vars personalizzate 'performers' e 'summary' per gli eventi.
*/
function wpse_288345_register_event_query_vars( $vars ) {
$vars[] = 'performers';
$vars[] = 'summary';
return $vars;
}
add_filter( 'query_vars', 'wpse_288345_register_event_query_vars' );
/**
* Decide quale template caricare
*/
function wpse_288345_load_performers_or_summary_template( $template ) {
// Ottieni le query vars pubbliche
$performers = (int) get_query_var( 'performers', 0 );
$summary = (int) get_query_var( 'summary', 0 );
// Se performer = 1 allora siamo sul link event/performers
if( $performers === 1 ) {
$template = locate_template( array( 'single-event-performers.php' ) );
}
// Se summary = 1 allora siamo sul link event/summary
if( $summary === 1 ) {
$template = locate_template( array( 'single-event-summary.php' ) );
}
if($template == '') {
throw new \Exception('Nessun template trovato');
}
return $template;
}
add_filter( 'template_include', 'wpse_288345_load_performers_or_summary_template' );

Ecco l'approccio alternativo che ho fatto funzionare, utilizzando un parametro GET e istruzioni condizionali.
Sulla pagina di elenco alternativa, ho aggiunto '?template=kiosk' ai permalink.
Nel template dei singoli elementi (single-plans.php) ho aggiunto il seguente codice all'inizio del template (e naturalmente 'endif' alla fine del template):
$kiosk = $_GET['template']; if(isset($kiosk)) :
Poi, throughout il template, ho creato delle istruzioni condizionali basate sulla presenza o meno del parametro, per visualizzare il contenuto in modo appropriato:
if(isset($kiosk)) { // mostra versione kiosk } else { // mostra versione standard }

Stavo provando quasi esattamente lo stesso codice, e non funzionava. C'è solo una modifica da apportare per farlo funzionare completamente. Basta aggiungere locate_template
a una riga.
Cambiare
if ( $alt === 'alt' ) $template = 'single-kioskplans.php';
in
if ( $alt === 'alt' ) $template = locate_template('single-kioskplans.php');
Il codice completo sarà così:
add_action('template_redirect', 'change_plans_plink');
function change_plans_plink() {
if (is_page_template('page_kioskoverview.php')) {
add_filter( 'post_link', 'plans_query_string', 10, 2 );
}
}
function plans_query_string( $url, $post ) {
if ( $post->post_type === 'plans' ) {
$url = add_query_arg( array('style'=>'alt'), $url );
}
return $url;
}
//designa un modello single alternativo per il link alt sopra
add_action('template_include', 'kiosk_plan_single');
function kiosk_plan_single($template) {
if( is_singular('plans') ) {
$alt = filter_input(INPUT_GET, 'style', FILTER_SANITIZE_STRING);
if ( $alt === 'alt' ) $template = locate_template('single-kioskplans.php');
}
return $template;
}
