Obtener el nombre del archivo de plantilla actual

58

Encontré esto para mostrar el nombre actual del archivo utilizado 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 = '(default)' ; }
    $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 plantilla, obtengo esta entrada extra fea:

captura de pantalla

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

chodorowicz
fuente
2
@chodorowicz: si bien me detendré un paso antes de llamar a la selección functions.phpcomo un error, estaré completamente de acuerdo con su premisa. Para empeorar las cosas, escaneé el código central de WordPress y encontré alrededor de 5 lugares donde podría haber un enganche para permitirle manejar este problema, pero no encontré ninguno. Sugeriría publicar un ticket en core.trac.wordpress.org .
MikeSchinkel
@ MikeSchinkel: gracias por comentar, pero no template_includeengancha, ¿qué t31os sugirió, resolver el problema? O tal vez te he entendido mal.
chodorowicz
1
@MikeSchinkel: ya tiene un parche :) core.trac.wordpress.org/ticket/16689
chodorowicz
1
He creado un nuevo complemento para mostrar la plantilla actual. Compruébelo en wordpress.org/extend/plugins/display-template-name
44
^ ie. tomaste el código de mi respuesta y lo envolviste en un complemento. E hiciste todo eso sin proporcionar ningún crédito al origen, ni a mí ni al WP stackexchange ... agradable ...: /
t31os

Respuestas:

69

Puede establecer una variable global durante el template_includefiltro y luego verificar esa variable global para ver qué plantilla se ha incluido.

Naturalmente, no querría la ruta completa junto con el archivo, por lo que recomendaría truncar el nombre del archivo utilizando la basenamefunción de PHP .

Código de ejemplo:
dos funciones, una para configurar el global y otra para invocarlo.

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 puede recurrir a get_current_templatedonde sea que lo necesite en los archivos de tema, y ​​tenga en cuenta que esto naturalmente debe ocurrir después de que la template_includeacción se haya disparado (no tendrá que preocuparse por esto si la llamada se realiza dentro de un archivo de plantilla).

Para las plantillas de página, hay que is_page_template()tener en cuenta que solo ayudará en el caso de las plantillas de página (una función mucho menor de capturar todas ).

Información sobre las funciones utilizadas o mencionadas anteriormente:

t31os
fuente
¡Increíble! Sabía que tenía que haber una manera más simple.
racl101
Uno para agregar al principio de mi lista de funciones de depuración.
Julio
24

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 (tiendo a hacer eco en footer.php en el comentario HTML)

<?php global $template; echo basename($template); ?>
chodorowicz
fuente
1
Eso no va a funcionar con get-template-parte para que lo sepas, sólo muestra single.php (por ejemplo) y no el archivo que se encuentra.
m-Torin
Sí, es verdad. Para obtener el nombre del archivo incluido, probablemente necesite usar algo como estoecho __FILE__;
chodorowicz
esto está bien, por ejemplo, en los casos en que modifica la plantilla predeterminada sin asignarla a una publicación en backoffice. Por ejemplo, utilizando rutas personalizadas y el filtro template_include. Gracias.
Luca Reghellin
¿Cómo podría hacer esto dentro de un bucle? Estoy tratando de enviar la URL a una página de cada archivo de plantilla.
JacobTheDev
@JacobTheDev puede usar echo __FILE__, porque esto no funcionará, solo muestra la plantilla principal inicial
chodorowicz
17

Entre las funciones nativas de WP como get_template_part () y la nativa de PHP, la forma más confiable de ver los archivos de tema utilizados es buscar una lista de todos los archivos incluidos y filtrar lo que no pertenece al tema (o temas cuando se usa la combinación 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 );
Rarst
fuente
9

Una adición (más código dulce) a otras respuestas aquí.

Nombre de la plantilla

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

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

Nombre del archivo

Cuando solo desee hacer eco del nombre del archivo de plantilla actual , vaya con lo siguiente

Editar: Aquí está la nueva versión del complemento envuelto en una clase. Muestra el nombre del archivo de plantilla actual, así como el nombre del archivo de jerarquía de plantilla en el gancho de cierre en la parte inferior de la página.

Lo que te dice el complemento:

  • ¿Es la plantilla del padre del tema hijo / actual?
  • ¿Se sirve la plantilla desde una subcarpeta? En caso afirmativo: te dice el nombre
  • El nombre del archivo de plantilla.

Simplemente copie el siguiente código en un archivo y asígnele un nombre wpse10537_template_info.php, cárguelo en su directorio de complementos y actívelo.

<?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 complemento también puede ejecutarse como MU-Plugin.

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

emperador
fuente
1
template_redirectno está pasando nada, creo que te estás confundiendo template_include. También verificaría si dentro del filtro en lugar de si la var estática está llena. Si algún código decide ejecutar hook tiempo adicional, puede destruir cosas.
Rarst
@Rarst Done / Fixed. Gracias por la pista y señalando el nombre del filtro.
kaiser
5

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

$template = get_post_meta( $post->ID, '_wp_page_template', true );
echo "Template: " . $template;
Simon Blackbourn
fuente
2
Sí, lo sé, pero el problema es que solo funciona cuando una página tiene una plantilla establecida. Lo bueno de un código que he publicado es que le dirá si la página actual está utilizando front-page.php, index.php, single.php, page.phpo cualquier otro archivo. Su código muestra el nombre de la plantilla solo para páginas con una plantilla de página personalizada.
chodorowicz
ah, lo siento, mi malentendido de tu pregunta.
Simon Blackbourn
@SimonBlackbourn Es ayuda para mi requerimiento. Gracias.
KarSho
3

Esto no aborda todas las preguntas del OP, pero el código a continuación es ciertamente más elegante que las expresiones regulares y analiza el archivo de plantilla en sí.

Si está en una página que usa una plantilla de página y desea obtener el nombre de la plantilla de página (es decir, el nombre legible por humanos que definió en los comentarios en la parte superior de su archivo PHP de plantilla), puede usar esta pequeña 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];
}

Quería obtener el nombre de la plantilla porque estaba realmente harto de los nombres de clase tontos que la función incorporada de WordPress body_classcrea cuando usas una plantilla. Afortunadamente, hay un gancho de filtro al final de esa función que le permite agregar sus propios nombres de clase también. 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á lo que haya llamado su plantilla de página, reemplazará espacios con guiones y hará que todo esté en minúsculas para que se vea como todas las otras clases de WordPress.

Tom Auger
fuente
0

Hay un problema con la preg_match_alllínea. Intenta esto en su lugar:

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

Además, puede usar if (!is_admin()) { .... }para ejecutar cosas solo en la interfaz.

wyrfel
fuente
Gracias por su sugerencia, no resuelven el problema, pero me dirigieron a soluciones. Resulta que WP, mientras genera la lista de plantillas, está buscando incluso functions.phpencontrar el archivo "/Template Name:(.*)\n/siU"y, por lo tanto, lo trata functions.phpcomo un archivo de plantilla. Creo que este es un error de WP, ni siquiera debería mirar este archivo. La solución: mover el archivo al subdirectorio.
chodorowicz
@chodorowicz: Eso no es un error en WP, es un error en su función.
wyrfel
Entonces, básicamente, WP le prohíbe poner la cadena "Nombre de plantilla:" (incluso en el comentario) en el functions.phparchivo. Para mí, personalmente, eso es un error, (pequeño, pero de todos modos) pero supongo que eso depende de la discusión. Creo que no se puede decir que la función en sí es defectuosa.
chodorowicz
WP no te prohíbe hacer nada. Pero WP tampoco le promete que puede recorrer un debug_backtrace () para averiguar qué archivo de plantilla está utilizando. El hecho de que lo haya encontrado en un foro de soporte de WP no significa que sea un código oficialmente compatible. Como puede ver, su función explícitamente excluye footer.php. También puede agregar otra condición que excluya functions.php. Por cierto: su función no busca Template Namedentro de cada uno de los archivos, su ciclo ha terminado mucho antes.
wyrfel
El problema no fue con debug_backtrace(): puedo eliminar todo el código y simplemente dejarlo preg_match_all("/Template Name..., o incluso solo // Template Name:y WP lo trata functions.phpcomo un archivo de plantilla, pero gracias por los comentarios: este es un problema tan único que, como usted dice, no es justo decir Es un error. La solución t31os es limpia y resuelve todo el problema. Saludos
chodorowicz
0

Juega junto 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 saber qué página de plantilla sirve la página actual?

si la admin-bar stuffruta se muestra en la parte superior o en cualquier otro archivo, cambie el nombre del archivo template-loader.phpen esta línea de código a: cualquier nombre de archivo del que deba separarse.

si necesita esto en la barra de administración, use la priotity correcta (la más temprana) para asegurarse de que no se ingresen archivos al final de esta lista. Por ejemplo:

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

La prioridad -5hace que se cargue primero. La clave es representar esta línea en el momento correcto.

No devuelve el archivo de plantilla "actual", sino todo el actual en uso para la carga de página actual. Tal vez "cortar" con algo de lógica de esa idea .

La get_included_files()"última" clave es el último archivo incluido registrado, probablemente la última plantilla / archivo / parte utilizada en el pie de página por el widget de la barra lateral o algo así. Probablemente, los archivos incluidos en cos mutiple no se vuelven a registrar / rellenan nuevamente 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 informe como incluido, hasta que se haya incluido . Entonces es probable que sea demasiado tarde para usar el escenario.

La mayor parte del "tiempo" que le gustaría:

$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 principal de Wordpress get_template_part. ¡Rediseña tus necesidades en su lugar! Tal vez loop_start(), in_the_loop()y add_action('the_post')tiene la solución que desea, para alterar los datos dependiendo de la plantilla que se cargará para cada entrada dentro de un ciclo.

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