Obtener el nombre del archivo de plantilla actual

26 feb 2011, 17:47:14
Vistas: 155K
Votos: 81

He encontrado esto para mostrar el nombre actual del archivo usado en la plantilla:

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 = '(predeterminado)' ; }
    $template_file = array_pop(explode('/themes/', basename($template_file)));
    return $template_file . ' > '. $template_name ;
}

Fuente: obtener el nombre de la plantilla de página en una página

Funciona bastante bien, excepto que en el backend, en el cuadro de selección de plantillas, obtengo esta entrada extra poco atractiva:

captura de pantalla

¿Alguien tiene alguna idea de cómo arreglarlo? Ni siquiera sé por qué esta función se llama en el backend. ¿Existe una función condicional como is_frontend() - tal vez esto resolvería el problema?

9
Comentarios

@chodorowicz - Aunque me detendré un paso antes de llamar a la selección de functions.php como un error, estoy completamente de acuerdo con tu premisa. Para empeorar las cosas, escaneé el código núcleo de WordPress y encontré alrededor de 5 lugares donde podría haber habido un hook que permitiera manejar este problema, pero no encontré ninguno. Sugeriría publicar un ticket en http://core.trac.wordpress.org.

MikeSchinkel MikeSchinkel
26 feb 2011 22:13:34

@MikeSchinkel - gracias por el comentario, pero ¿no resuelve el problema el hook template_include que sugirió t31os? O tal vez te he entendido mal.

chodorowicz chodorowicz
27 feb 2011 17:29:35

@chodorowicz - Ahora me tienes muy confundido. La respuesta que dio @t31os resuelve un problema muy diferente del que entendí que estabas preguntando, basado en tu pregunta y tus comentarios subsiguientes a otras respuestas. Pero si la respuesta de @t31os resolvió tu necesidad real, entonces mi confusión aquí no es importante ya que tu pregunta ha sido respondida.

MikeSchinkel MikeSchinkel
27 feb 2011 18:21:23

Sí, la necesidad real era mostrar el nombre del archivo de tema actualmente utilizado, el código que publiqué tenía un error (que puede resolverse moviendo la función fuera de la carpeta principal del tema), pero la solución de @t31os es mucho más limpia y cumple con la necesidad. Pero, si entiendo correctamente, el problema real (que WP no debería intentar leer functions.php como archivo de plantilla de página) aún persiste. Intentaré publicarlo en trac, no lo he hecho todavía. ¡Saludos!

chodorowicz chodorowicz
27 feb 2011 18:44:34

@MikeSchinkel - ya tiene un parche :) http://core.trac.wordpress.org/ticket/16689

chodorowicz chodorowicz
28 feb 2011 19:33:19

@chodorowicz - Sí, mi comentario abordaba el problema real, evitando que WP intente leer functions.php y/o permitiendo escribir un hook para cambiar lo que se devuelve. Me alegra ver que encontraste un parche en lugar de duplicarlo; es tan difícil encontrar esos tickets existentes.

MikeSchinkel MikeSchinkel
28 feb 2011 20:57:16

He creado un nuevo plugin para mostrar la plantilla actual. Puedes verlo en http://wordpress.org/extend/plugins/display-template-name/

User User
1 jun 2012 14:32:12

^ es decir, tomaste el código de mi respuesta y lo envolvíste en un plugin. Y lo hiciste todo sin dar ningún crédito al origen, ni a mí ni a WP stackexchange... bonito... :/

t31os t31os
31 mar 2014 00:08:14
Mostrar los 4 comentarios restantes
Todas las respuestas a la pregunta 9
3
80

Podrías establecer una variable global durante el filtro template_include y luego verificar esa variable global para saber qué plantilla se ha incluido.

Naturalmente, no querrás la ruta completa junto con el archivo, así que recomiendo truncar hasta solo el nombre del archivo usando la función basename de PHP.

Código de ejemplo:
Dos funciones, una para establecer la global, otra para llamarla.

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

Luego puedes llamar a get_current_template donde lo necesites en los archivos del tema, teniendo en cuenta que esto debe ocurrir después de que se haya ejecutado la acción template_include (no tendrás que preocuparte por esto si la llamada se hace dentro de un archivo de plantilla).

Para plantillas de página existe is_page_template(), teniendo en cuenta que esto solo ayuda en el caso de plantillas de página (una función mucho menos general).

Información sobre las funciones usadas o referenciadas arriba:

27 feb 2011 02:40:03
Comentarios

¡Increíble! Sabía que tenía que haber una forma más sencilla.

racl101 racl101
9 mar 2013 00:11:02

Una función más para añadir a la parte superior de mi lista de funciones de depuración.

Jules Jules
17 jul 2013 00:41:27

Las personas también pueden estar interesadas en las funciones integradas is_single, is_attachment, is_singular, is_page y otras is_... funciones.

Fabien Snauwaert Fabien Snauwaert
7 abr 2022 10:22:03
5
46

aparentemente esto es suficiente:

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

o simplemente usarlo directamente en la plantilla (suelo mostrarlo en footer.php dentro de un comentario HTML)

<?php global $template; echo basename($template); ?>
9 abr 2011 19:25:16
Comentarios

Eso no funcionará con get-template-part, solo muestra single.php (por ejemplo) y no el archivo en el que está.

MTT MTT
25 sept 2012 18:11:09

Sí, es cierto. Para obtener el nombre del archivo incluido probablemente necesitarías usar algo como esto echo __FILE__;

chodorowicz chodorowicz
5 oct 2012 15:25:39

esto está bien, por ejemplo en casos cuando modificas la plantilla predeterminada sin asignarla a una publicación en el backoffice. Por ejemplo usando rutas personalizadas y el filtro template_include. Gracias.

Luca Reghellin Luca Reghellin
15 sept 2016 13:05:23

¿Cómo podría hacer esto dentro de un bucle? Estoy intentando mostrar la URL de una página por cada archivo de plantilla.

JacobTheDev JacobTheDev
28 feb 2017 17:07:22

@JacobTheDev quizás usando echo __FILE__ - porque esto no funcionará, solo muestra la plantilla principal inicial

chodorowicz chodorowicz
8 mar 2017 00:08:06
0
18

Entre las funciones nativas de WordPress como get_template_part() y los includes nativos de PHP, la forma más confiable de ver los archivos del tema utilizados es obtener una lista de todos los archivos incluidos y filtrar aquellos que no pertenecen al tema (o temas cuando se usa una combinación de tema padre e hijo):

$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 );
1 mar 2013 20:27:00
2
12

Un complemento (más código interesante) a otras respuestas aquí.

Nombre de la Plantilla

Para obtener solo el nombre de la plantilla de página actual, usa la siguiente línea.

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

Nombre del Archivo

Cuando solo quieres mostrar el nombre del archivo de plantilla actual, usa lo siguiente:

Edición: Aquí está la nueva versión del plugin encapsulada en una clase. Muestra tanto el nombre del archivo de plantilla actual como el nombre del archivo en la jerarquía de plantillas en el hook shutdown al final de la página.

Lo que te dice este plugin:

  • ¿La plantilla es del tema padre o del tema hijo/actual?
  • ¿La plantilla se sirve desde un subdirectorio? Si es así: Te dice el nombre
  • El nombre del archivo de plantilla.

Solo copia el siguiente código en un archivo y nómbralo wpse10537_template_info.php, súbelo al directorio de plugins y actívalo.

<?php
/** Plugin Name: (#10537) »kaiser« Obtener nombre de archivo de plantilla */

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(
                 "Archivo de plantilla"
                ,basename( $file )
            );
            return $file;
        }

        // Retorna variable estática en llamada echo fuera del filtro
        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( "Plantilla", $slug );

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

        $this->to_stack(
             "Plantilla (en subdirectorio)"
            ,str_replace( "/", "", strstr( $slug, "/" ) )
        );
    }

    public function is_parent_template()
    {
        if ( ! is_null( wp_get_theme()->parent ) )
            return $this->to_stack( 'del tema padre' );

        $this->to_stack( 'del tema actual/hijo' );
    }

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

} // endif;

Este plugin también puede ejecutarse como MU-Plugin.

Luego puedes simplemente llamar wpse10537_get_template_name() en cualquier punto (por ejemplo en una plantilla de tema). Esto evita saturar el espacio de nombres global.

8 sept 2012 05:16:18
Comentarios

template_redirect no está pasando nada, creo que lo estás confundiendo con template_include. También verificaría si dentro del filtro en lugar de si la variable estática está llena. Si algún código decide ejecutar el hook adicionalmente puede arruinar las cosas.

Rarst Rarst
15 sept 2012 20:42:16

@Rarst Hecho/Corregido. Gracias por la sugerencia y señalar el nombre del filtro.

kaiser kaiser
15 sept 2012 22:18:02
3

El nombre de la plantilla se almacena en la tabla postmeta, por lo que todo lo que necesitas hacer es colocar esto en algún lugar de tu bucle:

$template = get_post_meta( $post->ID, '_wp_page_template', true );
echo "Plantilla: " . $template;
26 feb 2011 19:51:28
Comentarios

Sí, lo sé, pero el problema es que solo funciona cuando una página tiene una plantilla establecida. Lo bueno del código que publiqué es que te dirá si la página actual está usando front-page.php, index.php, single.php, page.php o cualquier otro archivo. Tu código muestra el nombre de la plantilla solo para páginas con una plantilla personalizada.

chodorowicz chodorowicz
26 feb 2011 20:05:17

Ah, lo siento, malinterpreté tu pregunta.

Simon Blackbourn Simon Blackbourn
26 feb 2011 20:23:54

@SimonBlackbourn Es útil para mi requerimiento. Gracias.

KarSho KarSho
8 oct 2013 10:04:02
0

Esto no responde completamente a la pregunta del OP, pero el código siguiente es ciertamente más elegante que usar expresiones regulares y analizar el archivo de plantilla directamente.

Si estás en una Página que utiliza una Plantilla de Página, y quieres obtener el Nombre de la plantilla de página (es decir, el nombre legible por humanos que definiste en los comentarios al inicio de tu archivo PHP de plantilla), puedes usar este pequeño fragmento:

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

Quería obtener el nombre de la plantilla porque estaba realmente cansado de los nombres de clase ridículamente largos que la función incorporada de WordPress body_class crea cuando usas una plantilla. Afortunadamente, hay un filtro al final de esa función que te permite añadir tus propios nombres de clase. Aquí está mi filtro. Espero que alguien lo encuentre ú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;
}

Este filtro tomará el nombre que le diste a tu plantilla de página, reemplazará los espacios con guiones y convertirá todo a minúsculas para que se vea como todas las demás clases de WordPress.

1 may 2013 04:56:21
5

Hay un problema con la línea de preg_match_all. Prueba esto en su lugar:

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

También puedes usar if (!is_admin()) { .... } para ejecutar cosas solo en el frontend.

26 feb 2011 18:43:26
Comentarios

Gracias por la sugerencia, no resuelven el problema, pero me orientaron hacia soluciones. Resulta que WP, al generar la lista de plantillas, incluso busca en functions.php encuentra el "/Template Name:(.*)\n/siU" y por lo tanto trata el functions.php como un archivo de plantilla. Creo que esto es un error de WP, no debería siquiera mirar este archivo. La solución: mover el archivo a un subdirectorio.

chodorowicz chodorowicz
26 feb 2011 19:33:30

@chodorowicz: Eso no es un error en WP, es un error en tu función.

wyrfel wyrfel
26 feb 2011 20:18:54

Básicamente, WP te prohíbe poner la cadena "Template Name:" (incluso en un comentario) en el archivo functions.php. Para mí, personalmente, eso es un error (pequeño, pero al fin y al cabo), pero eso está abierto a discusión, supongo. No creo que puedas decir que la función en sí tiene un error.

chodorowicz chodorowicz
26 feb 2011 21:14:01

WP no te prohíbe hacer nada. Pero WP tampoco te promete que puedas iterar sobre un debug_backtrace() para descubrir qué archivo de plantilla estás usando. Solo porque lo encontraste en un foro de soporte de WP no significa que sea código oficialmente soportado. Como podrás ver, tu función excluye explícitamente footer.php. Igualmente podrías añadir otra condición que excluya functions.php. Por cierto: tu función no busca Template Name dentro de cada uno de los archivos, tu bucle terminó mucho antes de eso.

wyrfel wyrfel
27 feb 2011 08:00:12

El problema no estaba con debug_backtrace() - puedo eliminar todo el código y dejar solo preg_match_all("/Template Name..., o incluso solo // Template Name: y WP trata entonces a functions.php como archivo de plantilla, pero gracias por los comentarios - este es un problema tan único que, como dices, no es justo decir que es un bug. La solución de t31os es limpia y resuelve todo el problema. Saludos.

chodorowicz chodorowicz
27 feb 2011 13:56:31
0

Juega con:

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 en:

¿Cómo descubrir qué plantilla está sirviendo la página actual?

Si la ruta de admin-bar stuff aparece en la parte superior, o cualquier otro archivo, cambia el nombre de archivo template-loader.php en esta línea de código por: cualquier nombre de archivo desde el cual necesites partir.

Si necesitas esto en la barra de administración, usa la prioridad correcta (la más temprana) para asegurarte de que no se añadan archivos al final de esta lista. Por ejemplo:

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

La prioridad -5 asegura que se cargue primero. La clave es ejecutar esta línea en el momento adecuado.

No devuelve el archivo de plantilla "actual", sino todos los que están en uso para la carga de la página actual. Quizás se pueda "extraer" con algo de lógica a partir de esta idea.

La última clave de get_included_files() es el último archivo incluido registrado, probablemente el último archivo/parte de plantilla utilizado en el pie de página por un widget de la barra lateral o algo similar. Probablemente, porque múltiples archivos incluidos no se vuelven a registrar/poblar en get_included_files().

De lo contrario, la intención debe ser clara para hackear este problema. No hay forma de que un archivo incluido se reporte a sí mismo como incluido, hasta que ha sido incluido. Entonces probablemente es demasiado tarde para usar este escenario.

La mayoría de las "veces" te gustaría algo como:

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

Pero eso no es posible si la plantilla se carga fuera del método central de WordPress get_template_part. ¡Replantea tus necesidades! Quizás loop_start(), in_the_loop() y add_action('the_post') tengan la solución que buscas, para alterar datos dependiendo de la plantilla que se cargará para cada entrada dentro de un bucle.

15 sept 2017 09:49:57
0
-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
17 feb 2016 10:54:16