获取当前模板文件的名称


57

我发现它可以显示模板中使用的文件的当前名称:

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

来源:获取页面上页面模板的名称

它工作得很好,除了在后端的模板选择框中,我得到了这个丑陋的额外条目:

屏幕截图

有人知道如何解决吗?我什至不知道为什么在后端调用此函数。是否有类似的条件函数is_frontend()-也许这可以解决问题?


2
@chodorowicz-尽管我将选择functions.php错误作为错误的目标仅停留了一步,但我会完全同意您的前提。更糟糕的是,我扫描了WordPress核心代码,发现了大约5个可能存在钩子的地方,可以让您处理此问题,但我没有发现。我建议在core.trac.wordpress.org上发布票证。
MikeSchinkel 2011年

@MikeSchinkel-感谢您的评论,但是没有template_include钩住,哪个t31os建议解决此问题?也许我误会了你。
chodorowicz 2011年

1
@MikeSchinkel-它已经有一个补丁:) core.trac.wordpress.org/ticket/16689
chodorowicz

1
我制作了一个新插件,以显示当前模板。在wordpress.org/extend/plugins/display-template-name

4
^即。您从我的答案中获取了代码,并将其包装到插件中。而且您所做的所有事情都没有对来源进行任何说明,无论是我本人还是WP
stackexchange

Answers:


68

您可以在template_include过滤器中设置一个全局变量,然后在以后检查该全局变量以查看包含了哪个模板。

您自然不希望带有文件的完整路径,因此我建议使用PHP basename函数将其截断为文件名。

示例代码:
两个函数,一个用于设置全局,一个用于调用全局。

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

然后,get_current_template您可以在主题文件中的任何位置调用它,并注意到在template_include操作触发后自然会发生这种情况(如果调用是在模板文件中进行的,则无需担心)。

对于页面模板is_page_template(),请记住,仅在页面模板的情况下才有用(更不用说捕获所有功能)。

上面使用或引用的功能的信息:


太棒了!我知道必须有一个更简单的方法。
racl101 2013年

在我的调试功能列表的顶部添加一个。
Jules

22

显然这已经足够:

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

或直接在模板中使用它(我倾向于在HTML注释中的footer.php中回显)

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

1
这不会只是让你知道GET-模板的一部分工作,那只能说明single.php中(例如),而不是文件时,它是英寸
M-托林

对,是真的。要获取包含文件的名称,您可能需要使用类似这样的内容echo __FILE__;
chodorowicz 2012年

这很好,例如,在您修改默认模板而不将其分配给后台的帖子的情况下。例如,使用自定义路由和template_include过滤器。谢谢。
卡·雷格尔林

我如何在一个循环中做到这一点?我正在尝试将URL输出到每个模板文件的一页。
JacobTheDev '17

@JacobTheDev可能正在使用echo __FILE__-因为这将无法工作,因此仅显示主要的初始模板
chodorowicz

17

在诸如get_template_part()之类的本机WP函数与PHP的本机之间,查看使用的主题文件的最可靠方法是获取所有包含文件的列表,并过滤掉不属于主题的内容(或使用父级和子级组合时的主题) :

$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

这里是其他答案的补充(更甜蜜的代码)。

模板名称

要仅获取当前页面模板名称,请使用以下行。

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

文档名称

当您只想回显当前模板文件名时,请执行以下操作

编辑:这是包装在类中的插件的新版本。它在页面最底部的关闭钩子中显示当前模板文件名以及模板层次结构文件名。

插件告诉您的内容:

  • 模板是否来自子主题/当前主题的父主题?
  • 模板是从子文件夹提供的吗?如果是:告诉您名称
  • 模板文件名。

只需将以下代码复制到文件中并命名wpse10537_template_info.php,然后将其上传到您的plugins目录并激活即可。

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

该插件也可以作为MU-Plugin运行。

然后,您可以wpse10537_get_template_name()在任何时候简单地调用(例如主题模板)。这样可以避免使全局名称空间混乱。


1
template_redirect没有传递任何东西,我认为您对此感到困惑template_include。另外我会检查是否在过滤器内部,而不是是否填充了静态var。如果某些代码决定运行额外的钩子,则可能会破坏事情。
拉斯特

@完成/已修复。感谢您的提示,并指出了过滤器名称。
kaiser 2012年

5

模板名称存储在postmeta表中,因此您所需要做的就是将其放在循环中的某个位置:

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

2
是的,我知道这一点,但是问题在于它仅在页面具有设置的模板时才有效。关于我发布的代码很酷的事情是,如果当前页面使用它会告诉你front-page.phpindex.phpsingle.phppage.php或任何其他文件。您的代码仅显示具有自定义页面模板的页面的模板名称。
chodorowicz 2011年

啊,对不起-我对您的问题的误解。
西蒙·布莱克本

@SimonBlackbourn这对我的要求有所帮助。谢谢。
KarSho

3

这不能解决OP的所有问题,但是下面的代码当然比正则表达式和解析模板文件本身更优雅。

如果您正在使用页面模板的页面上,并且想要获取页面模板的名称(即,您在模板PHP文件顶部的注释中定义的可读名称),则可以使用这个小金块:

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

我想获取模板名称,因为我真的很讨厌body_class在使用模板时内置的WordPress 函数创建的愚蠢的长屁股类名称。幸运的是,该函数的末尾有一个过滤器钩子,您还可以附加自己的类名。这是我的过滤器。希望有人觉得它有用:

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

该过滤器将采用您为页面模板命名的任何内容,用破折号代替空格,并将所有内容都转换为小写,使其看起来与所有其他WordPress类类似。


0

preg_match_all生产线有问题。尝试以下方法:

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

另外,您只能用于if (!is_admin()) { .... }在前端运行事物。


感谢您的建议,他们不能解决问题,但可以引导我进入解决方案。事实证明,WP在生成模板列表时正在寻找甚至functions.php找到"/Template Name:(.*)\n/siU",因此将其functions.php视为模板文件。我认为这是WP错误,甚至不应该查看此文件。解决方案:将文件移到子目录中。
chodorowicz 2011年

@chodorowicz:这不是WP中的错误,而是功能中的错误。
wyrfel

因此,基本上WP禁止您在文件中放入字符串“ Template Name:”(即使在注释中)functions.php。就我个人而言,这是一个错误(虽然很小,但无论如何),但我认为这取决于讨论。我认为您不能说该函数本身是错误的。
chodorowicz 2011年

WP不禁止您做任何事情。但是WP也不能保证您可以遍历debug_backtrace()来找出正在使用的模板文件。仅仅因为您在WP支持论坛上找到了它并不意味着它是官方支持的代码。如您所见,您的函数显式排除了footer.php。您也可以添加另一个不包含functions.php的条件。顺便说一句:您的函数不在Template Name每个文件中查找,您的循环早于此结束。
wyrfel 2011年

问题不在于debug_backtrace()-我可以删除所有代码,然后离开preg_match_all("/Template Name...,甚至可以// Template Name:将WP视为functions.php模板文件,但是感谢您的评论-这是一个独特的问题,正如您所说,这不公平这是一个错误。t31os解决方案很干净,可以解决整个问题。问候
chodorowicz 2011年

0

一起玩:

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

写在:

您如何找出哪个模板页面正在为当前页面提供服务?

如果admin-bar stuff路径显示在顶部或任何其他文件中,请template-loader.php将此代码行中的文件名更改为:您需要中断的任何filname。

如果需要在管理栏中进行此操作,请使用正确的优先级(最早)确保此列表末尾没有输入文件。例如:

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

优先-5确保先加载。关键是在适当的时候渲染这条线。

它不返回“当前”模板文件,而是返回当前用于页面加载的所有当前文件。也许从这个想法中得出一些逻辑“切出”

get_included_files()“最后”关键是最后的注册包括文件,通过侧边栏小工具什么的页脚使用propably的最后一个模板的文件/ -part。可能是因为cos mutiple包含的文件不会在get_included_files()中再次重新注册/填充。

否则,必须明确意图以解决该问题在包含文件之前,包含文件无法报告自己是否包含文件。然后,它很可能会晚使用该方案。

想要的大部分“时间” :

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

但是,如果将模板加载到的Wordpress核心方法之外,则不可能get_template_part。重新设计您的需求!也许loop_start()in_the_loop()并且add_action('the_post')具有您想要的解决方案,可以根据要为循环中每个条目加载的模板更改数据。


-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.