Obter o nome do arquivo de modelo atual

57

Eu encontrei isso para exibir o nome atual do arquivo usado no modelo:

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: obter o nome do modelo da página em uma página

Funciona muito bem, exceto que no back-end, na caixa de seleção de modelo, recebo esta entrada extra feia:

captura de tela

Alguém tem alguma idéia de como consertar isso? Nem sei por que essa função é chamada no back-end. Existe uma função condicional como is_frontend()- talvez isso resolva o problema?

chodorowicz
fonte
2
@chodorowicz - Embora eu pare um passo antes de chamar a seleção de functions.phpbug, eu concordo completamente com sua premissa. Para piorar as coisas, examinei o código principal do WordPress e encontrei cerca de 5 lugares onde poderia haver um gancho para permitir que você lidasse com esse problema, mas não encontrei nenhum. Sugiro que você publique um ticket no core.trac.wordpress.org .
26611 MikeSchinkel
@ MikeSchinkel - obrigado pelo comentário, mas o template_includehook, que t31os sugeriu, resolve o problema? Ou talvez eu tenha entendido mal você.
27411 chodorowicz
11
@MikeSchinkel - que já tem um remendo :) core.trac.wordpress.org/ticket/16689
chodorowicz
11
Eu criei um novo plugin para exibir o modelo atual. Verifique-o no wordpress.org/extend/plugins/display-template-name
4
^ ie. você pegou o código da minha resposta e o embrulhou em um plugin. E você fez tudo isso sem fornecer nenhum crédito à origem, nem eu nem o WP
stackexchange

Respostas:

68

Você pode definir uma variável global durante o template_includefiltro e depois verificar essa variável global para ver qual modelo foi incluído.

Você naturalmente não gostaria do caminho completo junto com o arquivo, então eu recomendo truncar o nome do arquivo usando a basenamefunção PHP .

Código de exemplo:
duas funções, uma para definir o global e outra para chamá-lo.

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'];
}

Em seguida, você pode recorrer get_current_templatesempre que precisar nos arquivos do tema, observando que isso naturalmente ocorre depois que a template_includeação foi acionada (você não precisará se preocupar com isso se a chamada for feita dentro de um arquivo de modelo).

Para os modelos de página is_page_template(), lembre-se de que isso só ajudará no caso de modelos de página (muito menos pegar todas as funções).

Informações sobre funções usadas ou referenciadas acima:

t31os
fonte
Impressionante! Eu sabia que tinha que haver uma maneira mais simples.
racl101
Um para adicionar ao topo da minha lista de funções de depuração.
Jules
23

aparentemente isso é suficiente:

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

ou apenas usá-lo diretamente no modelo (eu tendem a ecoar no footer.php no comentário HTML)

<?php global $template; echo basename($template); ?>
chodorowicz
fonte
11
Isso não vai funcionar com get-template-parte só assim você sabe, ele só mostra single.php (por exemplo) e não o arquivo que se encontra.
m-torin
Sim, é verdade. Para obter o nome do arquivo incluído, você provavelmente precisará usar algo parecido com istoecho __FILE__;
chodorowicz 5/12
isso é bom, por exemplo, nos casos em que você modifica o modelo padrão sem atribuí-lo a uma postagem no backoffice. Por exemplo, usando rotas personalizadas e o filtro template_include. Obrigado.
Luca Reghellin
Como eu poderia fazer isso dentro de um loop? Estou tentando gerar o URL para uma página de cada arquivo de modelo.
27617 JacobTheDev
@JacobTheDev talvez usando echo __FILE__- porque isso não vai funcionar, ele apresenta apenas principal, inicial template
chodorowicz
17

Entre as funções nativas do WP, como get_template_part () e o nativo do PHP, a maneira mais confiável de ver os arquivos do tema usados ​​é buscar a lista de todos os arquivos incluídos e filtrar o que não pertence ao tema (ou temas quando a combinação pai e filho é usada) :

$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 );
Rarst
fonte
9

Uma adição (código mais interessante) a outras respostas aqui.

Nome do modelo

Para obter apenas o nome do modelo de página atual , use a seguinte linha.

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

Nome do arquivo

Quando você quiser apenas repetir o nome do arquivo de modelo atual , siga as seguintes

Edit: Aqui está a nova versão do plugin agrupada em uma classe. Ele mostra o nome atual do arquivo de modelo, bem como o nome do arquivo de hierarquia de modelos no gancho de desligamento na parte inferior da página.

O que o plugin diz a você:

  • O modelo é o pai do filho / tema atual?
  • O modelo é exibido em uma subpasta? Se sim: informa o nome
  • O nome do arquivo de modelo.

Apenas copie o código a seguir em um arquivo e nomeie-o wpse10537_template_info.php, faça o upload para o diretório de plugins e ative-o.

<?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;

Este plugin também pode ser executado como MU-Plugin.

Você pode simplesmente ligar wpse10537_get_template_name()a qualquer momento (por exemplo, um modelo de tema). Isso evita bagunçar o espaço para nome global.

kaiser
fonte
11
template_redirectnão está passando nada, acho que você está confuso template_include. Além disso, eu verificaria se dentro do filtro, em vez de se a var estática estiver preenchida. Se algum código decidir executar o gancho por mais tempo, ele poderá danificar as coisas.
Rarst
@Rarst Feito / Fixo. Obrigado pela dica e apontando o nome do filtro.
Kaiser #
5

O nome do modelo é armazenado na tabela postmeta, então tudo o que você precisa fazer é colocar isso em algum lugar do seu loop:

$template = get_post_meta( $post->ID, '_wp_page_template', true );
echo "Template: " . $template;
Simon Blackbourn
fonte
2
Sim, eu sei disso, mas o problema é que ele funciona apenas quando uma página tem um modelo definido. A coisa legal sobre o código eu postei é que ele vai dizer se a página atual está usando front-page.php, index.php, single.php, page.phpou qualquer outro arquivo. Seu código exibe o nome do modelo apenas para páginas com modelo de página personalizado.
31811 chodorowicz
ah, desculpe - meu mal entendido da sua pergunta.
Simon Blackbourn
@SimonBlackbourn É ajuda para minha exigência. Obrigado.
KarSho
3

Isso não trata de todas as questões do OP, mas o código abaixo é certamente mais elegante que as expressões regulares e analisa o próprio arquivo de modelo.

Se você estiver em uma página que está usando um modelo de página e deseja obter o nome do modelo da página (ou seja: o nome legível por humanos que você definiu nos comentários na parte superior do arquivo PHP do modelo), você pode usar esta pequena 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];
}

Eu queria obter o nome do modelo porque estava realmente cansado dos nomes de classe idiotas que a body_classfunção interna do WordPress cria quando você está usando um modelo. Felizmente, existe um gancho de filtro no final dessa função para permitir que você adicione também seus próprios nomes de classe. Aqui está o meu filtro. Espero que alguém ache útil:

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;
}

Esse filtro pega o que você nomeou para o modelo da sua página, substitui espaços por hífens e deixa tudo em letras minúsculas para que pareça com todas as outras classes do WordPress.

Tom Auger
fonte
0

Há um problema com a preg_match_alllinha. Tente isso:

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

Além disso, você pode usar if (!is_admin()) { .... }para executar coisas apenas no frontend.

Wyrfel
fonte
Obrigado pela sugestão, eles não resolvem o problema, mas meio que me direcionaram para soluções. Acontece que o WP, ao gerar a lista de modelos, está procurando até functions.phpencontrar o "/Template Name:(.*)\n/siU"e, assim, trata o functions.phparquivo como modelo. Eu acho que isso é bug do WP, ele nem deveria olhar para esse arquivo. A solução: mova o arquivo para o subdiretório.
31411 chodorowicz
@chodorowicz: Isso não é um bug no WP, é um bug na sua função.
wyrfel
Então, basicamente, o WP proíbe que você coloque a string "Nome do modelo:" (mesmo no comentário) no functions.phparquivo. Para mim, pessoalmente, isso é um bug (pequeno, mas mesmo assim), mas é isso que está em discussão, suponho. Eu acho que você não pode dizer que a função em si é de buggy.
31811 chodorowicz
O WP não proíbe que você faça nada. Mas o WP também não promete que você pode percorrer um debug_backtrace () para descobrir qual arquivo de modelo você está usando. Só porque você o encontrou em um fórum de suporte do WP não significa que seja um código oficialmente suportado. Como você pode ver, sua função explora explicitamente footer.php. Você também pode adicionar outra condição que exclui functions.php. BTW: sua função não procura Template Nameem cada um dos arquivos; seu loop terminou muito antes disso.
wyrfel
O problema não estava com debug_backtrace()- eu posso remover todo o código e apenas sair preg_match_all("/Template Name..., ou até mesmo apenas // Template Name:e o WP o trata functions.phpcomo arquivo de modelo, mas obrigado pelos comentários - esse é um problema tão único que, como você diz, não é justo dizer é um bug. A solução t31os é limpa e resolve todo o problema. Cumprimenta.
27411 chodorowicz
0

Toque junto com:

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>';

Escrito em:

Como você descobre qual página de modelo está servindo a página atual?

se o admin-bar stuffcaminho estiver aparecendo na parte superior ou em qualquer outro arquivo, altere o nome do arquivo template-loader.phpnesta linha de código para: qualquer nome de arquivo do qual você precise interromper.

se você precisar disso na barra de administração, use a prioridade certa (antes) para garantir que nenhum arquivo seja inserido no final desta lista. Por exemplo:

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

prioridade -5faça com que ele carregue primeiro. A chave é renderizar essa linha no momento certo.

Ele não retorna o arquivo de modelo "atual", mas todo o atual em uso para o carregamento de página atual. Talvez "recorte" com alguma lógica dessa idéia .

A get_included_files()tecla "last" é o último arquivo incluído registrado, provavelmente o último arquivo-modelo / parte usado no rodapé pelo widget da barra lateral ou algo assim. Provavelmente, porque os arquivos incluídos em vários arquivos não são registrados / preenchidos novamente em get_included_files ().

Caso contrário, a intenção deve ser clara para solucionar esse problema . Não há como um arquivo incluído se reportar como incluído, até que tenha sido incluído . Então é provável que seja tarde demais para usar o cenário.

Na maioria das vezes "você gostaria " :

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

Mas isso não é possível se o modelo for carregado fora do método principal do Wordpress get_template_part. Redesenhe suas necessidades! Talvez loop_start(), in_the_loop()e add_action('the_post')tenha a solução que você deseja, altere os dados, dependendo do modelo que será carregado para cada entrada em um loop.

Jonas Lundman
fonte
-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
Shafi
fonte