Ottieni il nome del file modello corrente


58

Ho trovato questo per visualizzare il nome corrente del file utilizzato nel modello:

function get_template_name () {
    foreach ( debug_backtrace() as $called_file ) {
        foreach ( $called_file as $index ) {
            if ( !is_array($index[0]) AND strstr($index[0],'/themes/') AND !strstr($index[0],'footer.php') ) {
                $template_file = $index[0] ;
            }
        }
    }
    $template_contents = file_get_contents($template_file) ;
    preg_match_all("Template Name:(.*)\n)siU",$template_contents,$template_name);
    $template_name = trim($template_name[1][0]);
    if ( !$template_name ) { $template_name = '(default)' ; }
    $template_file = array_pop(explode('/themes/', basename($template_file)));
    return $template_file . ' > '. $template_name ;
}

Fonte: ottenere il nome del modello di pagina su una pagina

Funziona abbastanza bene, tranne che nel backend, nella casella di selezione del modello, ottengo questa brutta voce extra:

immagine dello schermo

Qualcuno ha idea di come risolverlo? Non so nemmeno perché questa funzione sia chiamata nel backend. Esiste una funzione condizionale come is_frontend(): forse questo risolverebbe il problema?


2
@chodorowicz - Mentre smetterò di fare un passo avanti nel chiamare la selezione functions.phpcome bug, concordo completamente con la tua premessa. A peggiorare le cose, ho scansionato il codice core di WordPress e ho trovato circa 5 posti in cui avrebbe potuto esserci un gancio per permetterti di gestire questo problema, ma non ne ho trovato nessuno. Suggerirei di pubblicare un biglietto su core.trac.wordpress.org .
MikeSchinkel,

@MikeSchinkel - grazie per il commento, ma il template_includegancio, suggerito da t31os, risolve il problema? O forse ti ho frainteso.
Chodorowicz,

1
@MikeSchinkel - ha già una patch :) core.trac.wordpress.org/ticket/16689
chodorowicz

1
Ho creato un nuovo plugin per visualizzare il modello corrente. Controllalo su wordpress.org/extend/plugins/display-template-name

4
^ ie. hai preso il codice dalla mia risposta e lo hai inserito in un plugin. E hai fatto tutto questo senza dare credito all'origine, né io né lo scambio di stack WP ... bello ...: /
t31os

Risposte:


69

È possibile impostare una variabile globale durante il template_includefiltro e successivamente verificare che sia possibile ottenere la variabile globale per vedere quale modello è stato incluso.

Naturalmente non vorrai il percorso completo insieme al file, quindi ti consiglio di troncare fino al nome del file usando la basenamefunzione di PHP .

Codice di esempio:
due funzioni, una per impostare il globale, una per richiamarla.

add_filter( 'template_include', 'var_template_include', 1000 );
function var_template_include( $t ){
    $GLOBALS['current_theme_template'] = basename($t);
    return $t;
}

function get_current_template( $echo = false ) {
    if( !isset( $GLOBALS['current_theme_template'] ) )
        return false;
    if( $echo )
        echo $GLOBALS['current_theme_template'];
    else
        return $GLOBALS['current_theme_template'];
}

Puoi quindi invocare get_current_templateovunque sia necessario nei file dei temi, notando che questo deve naturalmente verificarsi dopo che l' template_includeazione è stata attivata (non dovrai preoccuparti di questo se la chiamata viene effettuata all'interno di un file modello).

Per i modelli di pagina c'è is_page_template(), tenendo presente che aiuterà solo nel caso dei modelli di pagina (molto meno cattura tutte le funzioni).

Informazioni sulle funzioni utilizzate o citate sopra:


Eccezionale! Sapevo che doveva esserci un modo più semplice.
racl101,

Uno da aggiungere in cima al mio elenco delle funzioni di debug.
Jules,

24

apparentemente questo è abbastanza:

add_action('wp_head', 'show_template');
function show_template() {
    global $template;
    echo basename($template);
}

o semplicemente usalo direttamente nel template (tendo a fare eco in footer.php nel commento HTML)

<?php global $template; echo basename($template); ?>

1
Questo non funzionerà con get-template-part solo per quello che sai, mostra solo single.php (per esempio) e non il file in cui si trova.
m-torin

Si è vero. Per ottenere il nome del file incluso probabilmente dovresti usare qualcosa del genereecho __FILE__;
chodorowicz,

questo va bene, ad esempio nei casi in cui si modifica il modello predefinito senza assegnarlo a un post in backoffice. Ad esempio utilizzando percorsi personalizzati e il filtro template_include. Grazie.
Luca Reghellin,

Come potrei farlo in un ciclo? Sto provando a generare l'URL su una pagina di ciascun file modello.
JacobTheDev,

@JacobTheDev potrebbe essere utilizzato echo __FILE__- poiché non funzionerà, verrà visualizzato solo il modello iniziale principale
chodorowicz

17

Tra le funzioni WP native come get_template_part () e quelle native di PHP il modo più affidabile per vedere i file dei temi utilizzati è quello di recuperare l'elenco di tutti i file inclusi e filtrare tutto ciò che non appartiene al tema (o ai temi quando viene utilizzata la combinazione padre e figlio) :

$included_files = get_included_files();
$stylesheet_dir = str_replace( '\\', '/', get_stylesheet_directory() );
$template_dir   = str_replace( '\\', '/', get_template_directory() );

foreach ( $included_files as $key => $path ) {

    $path   = str_replace( '\\', '/', $path );

    if ( false === strpos( $path, $stylesheet_dir ) && false === strpos( $path, $template_dir ) )
        unset( $included_files[$key] );
}

var_dump( $included_files );

9

Un'aggiunta (codice più dolce) ad altre risposte qui.

Nome modello

Per ottenere solo il nome del modello di pagina corrente , utilizzare la seguente riga.

is_page() AND print get_page_template_slug( get_queried_object_id() );

Nome del file

Quando vuoi solo fare eco al nome del file modello corrente , procedi come segue

Modifica: ecco la nuova versione del plugin racchiusa in una classe. Mostra sia il nome del file del modello corrente, sia il nome del file della gerarchia dei modelli nel gancio di arresto nella parte inferiore della pagina.

Cosa ti dice il plugin:

  • Il modello è del genitore del bambino / tema attuale?
  • Il modello è offerto da una sottocartella? Se sì: ti dice il nome
  • Il nome del file modello.

Basta copiare il seguente codice in un file e denominarlo wpse10537_template_info.php, caricarlo nella directory dei plug-in e attivarlo.

<?php
/** Plugin Name: (#10537) »kaiser« Get Template file name */

if ( ! class_exists( 'wpse10537_template_name' ) )
{
    add_action( 'plugins_loaded', array( 'wpse10537_template_name', 'init' ) );

class wpse10537_template_name
{
    protected static $instance;

    public $stack;

    public static function init()
    {
        is_null( self :: $instance ) AND self :: $instance = new self;
        return self :: $instance;
    }

    public function __construct()
    {
        if ( is_admin() )
            return;

        add_action( 'wp', array( $this, 'is_parent_template' ), 0 );
        add_action( 'wp', array( $this, 'get_template_file' ) );
        add_action( 'template_include', array( $this, 'get_template_name' ) );
        add_action( 'shutdown', array( $this, 'get_template_name' ) );
    }

    public function get_template_name( $file )
    {
        if ( 'template_include' === current_filter() )
        {
            $this->to_stack(
                 "Template file"
                ,basename( $file )
            );
            return $file;
        }

        // Return static var on echo call outside of filter
        if (
            current_user_can( 'manage_options' )
            AND defined( 'WP_DEBUG' )
            AND WP_DEBUG 
        )
            return print implode( " &ndash; ", $this->stack );
    }

    public function get_template_file()
    {
        if ( ! is_post_type_hierarchical( get_post_type() ) )
            return;

        $slug = get_page_template_slug( get_queried_object_id() );
        if ( ! strstr( $slug, "/" ) )
            return $this->to_stack( "Template", $slug );

        $this->to_stack(
             "Subdirectory"
            ,strstr( $slug, "/", true )
        );

        $this->to_stack(
             "Template (in subdirectory)"
            ,str_replace( "/", "", strstr( $slug, "/" ) )
        );
    }

    public function is_parent_template()
    {
        if ( ! is_null( wp_get_theme()->parent ) )
            return $this->to_stack( 'from parent theme' );

        $this->to_stack( 'from current/child theme' );
    }

    public function to_stack( $part, $item = '' )
    {
        $this->stack[] = "{$part}: {$item}";
    }
} // END Class wpse10537_template_name

} // endif;

Questo plugin può funzionare anche come MU-Plugin.

Puoi quindi semplicemente chiamare wpse10537_get_template_name()in qualsiasi momento (ad esempio un modello di tema). Questo evita di ingombrare lo spazio dei nomi globale.


1
template_redirectnon sta passando nulla, penso che tu ti stia confondendo template_include. Inoltre verificherei se all'interno del filtro anziché se var varata statica. Se un po 'di codice decide di eseguire il hook in maniera aggiuntiva, può rovinare tutto.
Rarst

@Rarst Done / Fixed. Grazie per il suggerimento e per aver sottolineato il nome del filtro.
Kaiser,

5

Il nome del modello è memorizzato nella tabella postmeta, quindi tutto ciò che devi fare è metterlo da qualche parte nel tuo ciclo:

$template = get_post_meta( $post->ID, '_wp_page_template', true );
echo "Template: " . $template;

2
Sì, lo so, ma il problema è che funziona solo quando una pagina ha un modello impostato. La cosa più cool il codice che ho postato è che vi dirà se la pagina corrente utilizza front-page.php, index.php, single.php, page.phpo qualsiasi altro file. Il codice visualizza il nome del modello solo per le pagine con modello di pagina personalizzato.
Chodorowicz,

ah, scusa, il mio fraintendimento della tua domanda.
Simon Blackbourn,

@SimonBlackbourn È un aiuto per le mie esigenze. Grazie.
KarSho,

3

Questo non affronta tutta la domanda del PO, ma il codice seguente è sicuramente più elegante delle espressioni regolari e analizza il file modello stesso.

Se ti trovi in ​​una pagina che utilizza un modello di pagina e desideri ottenere il nome del modello di pagina (ovvero: il nome leggibile dall'utente che hai definito nei commenti nella parte superiore del file PHP del modello), puoi utilizzare questa piccola pepita:

if ( is_page() && $current_template = get_page_template_slug( get_queried_object_id() ) ){
    $templates = wp_get_theme()->get_page_templates();
    $template_name = $templates[$current_template];
}

Volevo ottenere il nome del modello perché ero davvero stufo dei nomi delle classi sciocche e lunghe che la body_classfunzione WordPress integrata crea quando si utilizza un modello. Fortunatamente c'è un hook di filtro alla fine di quella funzione per permetterti di aggiungere anche i tuoi nomi di classe. Ecco il mio filtro Spero che qualcuno lo trovi utile:

add_filter( 'body_class', 'gs_body_classes', 10, 2 );
function gs_body_classes( $classes, $class ){
    if ( is_page() && $current_template = get_page_template_slug( get_queried_object_id() ) ){
        $templates = wp_get_theme()->get_page_templates();
        $template_name = str_replace( " ", "-", strtolower( $templates[$current_template] ) );

        $classes[] = $template_name;
    }

    return $classes;
}

Questo filtro prenderà qualunque cosa tu abbia chiamato il tuo modello di pagina, sostituirà gli spazi con trattini e renderà tutto minuscolo in modo che assomigli a tutte le altre classi di WordPress.


0

C'è un problema con la preg_match_alllinea. Prova questo invece:

preg_match_all("/Template Name:(.*)\n/siU",$template_contents,$template_name);

Inoltre, puoi usare if (!is_admin()) { .... }per eseguire le cose solo sul frontend.


Grazie per il suggerimento, non risolvono il problema, ma mi hanno indirizzato verso soluzioni. Si scopre che WP, durante la generazione dell'elenco dei modelli, sta esaminando anche in functions.phptrova il "/Template Name:(.*)\n/siU"e quindi tratta il functions.phpfile modello. Penso che questo sia un bug WP, non dovrebbe nemmeno guardare questo file. La soluzione: sposta il file nella sottodirectory.
Chodorowicz,

@chodorowicz: Non è un bug in WP, è un bug nella tua funzione.
Wyrfel,

Quindi sostanzialmente WP ti proibisce di mettere la stringa "Template Name:" (anche nei commenti) nel functions.phpfile. Per me, personalmente, questo è un bug, (piccolo, ma comunque) ma suppongo che sia fino alla discussione. Penso che non si possa dire che la funzione stessa sia buggy.
Chodorowicz,

WP non ti proibisce di fare nulla. Ma anche WP non ti promette che puoi eseguire il loop su un debug_backtrace () per scoprire quale file modello stai usando. Solo perché l'hai trovato su un forum di supporto WP non significa che sia un codice ufficialmente supportato. Come puoi vedere, la tua funzione espone esplicitamente footer.php. Puoi anche aggiungere un'altra condizione che esclude funzioni.php. A proposito: la tua funzione non cerca Template Nameall'interno di ciascuno dei file, il tuo ciclo è terminato molto prima.
Wyrfel,

Il problema non era debug_backtrace(): posso rimuovere tutto il codice e lasciarlo preg_match_all("/Template Name..., o anche solo // Template Name:e WP tratta quindi functions.phpcome file modello, ma grazie per i commenti: questo è un problema così unico che, come dici tu, non è giusto dirlo è un bug. La soluzione t31os è pulita e risolve l'intero problema. Saluta.
Chodorowicz,

0

Gioca insieme a:

echo '<ul><li>'.implode('</li><li>', str_replace(str_replace('\\', '/', ABSPATH).'wp-content/', '', array_slice(str_replace('\\', '/', get_included_files()), (array_search(str_replace('\\', '/', ABSPATH).'wp-includes/template-loader.php', str_replace('\\', '/', get_included_files())) + 1)))).'</li></ul>';

Scritto a:

Come scopri quale pagina modello serve la pagina corrente?

se il admin-bar stuffpercorso viene visualizzato nella parte superiore o qualsiasi altro file, modifica il nome file template-loader.phpin questa riga di codice in: qualunque sia il nome file da cui devi interrompere.

se ne hai bisogno nella barra di amministrazione, usa la priorità giusta (prima) per assicurarti che nessun file sia inserito alla fine di questo elenco. Per esempio:

add_action('admin_bar_menu', 'my_adminbar_template_monitor', -5);

la priorità -5fa shure che carica prima. La chiave è rendere questa linea al momento giusto.

Non restituisce il file modello "corrente", ma tutta la corrente in uso per il caricamento della pagina corrente. Forse "ritagliato" con qualche logica da quell'idea .

La get_included_files()chiave "last" è l'ultimo file incluso registrato, probabilmente l'ultimo file-template / -part utilizzato nel piè di pagina dal widget della barra laterale o qualcosa del genere. Probabilmente, i file cos mutiple inclusi non si registrano nuovamente / popolano nuovamente in get_included_files ().

Altrimenti, l'intensione deve essere chiara per hackerare questo problema . Non è possibile che un file incluso venga segnalato come incluso, fino a quando non viene incluso . Quindi è probabilmente troppo tardi per utilizzare lo scenario.

La maggior parte del "tempo" vorresti :

$template = get_current_loaded_template();
if($template == 'single-product.php') add_filter('the_title' ....
if($template == 'format-gallery.php') add_action('post_thumbnail' ....

Ma ciò non è possibile se il modello viene caricato al di fuori del metodo principale di Wordpress di get_template_part. Riprogetta invece le tue esigenze! Forse loop_start(), in_the_loop()e add_action('the_post')ha la soluzione che desideri, per modificare i dati a seconda del modello che verrà caricato per ogni voce all'interno di un ciclo.


-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.