Получить имя текущего файла шаблона

58

Я нашел это, чтобы отобразить текущее имя файла, используемого в шаблоне:

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()- может быть, это решит проблему?

chodorowicz
источник
2
@chodorowicz - Хотя я остановлюсь на шаг, не называя выбор functions.phpошибкой, я полностью согласен с вашей предпосылкой. Чтобы усугубить ситуацию, я отсканировал основной код WordPress и нашел около 5 мест, где мог бы быть хук, позволяющий решить эту проблему, но я не нашел ни одного. Я бы предложил разместить тикет на core.trac.wordpress.org .
MikeSchinkel
@MikeSchinkel - спасибо за комментарий, но не template_includeперехват, который предложил t31os, решить проблему? Или, может быть, я вас неправильно понял.
chodorowicz
1
@MikeSchinkel - у него уже есть патч :) core.trac.wordpress.org/ticket/16689
chodorowicz
1
Я сделал новый плагин для отображения текущего шаблона. Проверьте это на wordpress.org/extend/plugins/display-template-name
4
^ то есть Вы взяли код из моего ответа и обернули его в плагин. И вы сделали все это, не отдавая должное ни источнику, ни мне, ни WP stackexchange ... nice ...: /
t31os

Ответы:

69

Вы можете установить глобальную переменную во время template_includeфильтра, а затем проверить эту глобальную переменную, чтобы увидеть, какой шаблон был включен.

Естественно, вам не нужен полный путь вместе с файлом, поэтому я бы порекомендовал обрезать до имени файла basenameфункцию PHP .

Пример кода:
две функции, одна для установки глобальной, другая для ее вызова.

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(), имея в виду , что только поможет в случае шаблонов страниц (гораздо меньше , поймать все функции).

Информация о функциях, используемых или упомянутых выше:

t31os
источник
Потрясающие! Я знал, что должен быть более простой способ.
racl101
Один добавить в начало моего списка функций отладки.
Жюль
24

видимо этого достаточно

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

или просто использовать его непосредственно в шаблоне (я склонен выводить его в footer.php в комментарии HTML)

<?php global $template; echo basename($template); ?>
chodorowicz
источник
1
Это не будет работать с get-template-part, просто вы знаете, он показывает только single.php (например), а не файл, в котором он находится.
m-torin
Да, это правда. Чтобы получить имя включенного файла, вам, вероятно, понадобится что-то вроде этогоecho __FILE__;
chodorowicz
Это хорошо, например, в случаях, когда вы изменяете шаблон по умолчанию, не назначая его посту в backoffice. Например, используя пользовательские маршруты и фильтр template_include. Спасибо.
Лука Регеллин
Как я мог сделать это в цикле? Я пытаюсь вывести URL на одну страницу каждого файла шаблона.
JacobTheDev
@JacobTheDev, возможно, использует echo __FILE__- потому что это не будет работать, он отображает только основной, исходный шаблон
chodorowicz
17

Между нативными функциями WP, такими как get_template_part () и нативным 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 );
Rarst
источник
9

Дополнение (более приятный код) к другим ответам здесь.

Имя Шаблона

Чтобы просто получить имя шаблона текущей страницы , используйте следующую строку.

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

Имя файла

Если вы просто хотите отобразить текущее имя файла шаблона , перейдите к следующему

Изменить: Вот новая версия плагина, завернутый в класс. Он отображает как текущее имя файла шаблона, так и имя файла иерархии шаблонов в обработчике завершения работы в самой нижней части страницы.

Что плагин говорит вам:

  • Шаблон от родителя дочерней / текущей темы?
  • Шаблон подается из подпапки? Если да: сообщит вам имя
  • Имя файла шаблона.

Просто скопируйте следующий код в файл и назовите его wpse10537_template_info.php, загрузите в каталог плагинов и активируйте его.

<?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-плагин тоже.

Затем вы можете просто позвонить wpse10537_get_template_name()в любой момент (например, в шаблоне темы). Это позволяет избежать загромождения глобального пространства имен.

кайзер
источник
1
template_redirectне проходит ничего, я думаю, что вы путаете с template_include. Также я бы проверил, если внутри фильтра, а не заполнен ли статический var Если какой-то код решит запустить ловушку дополнительное время, это может испортить вещи.
Первое
@Rarst Done / Исправлено. Спасибо за подсказку и указание на имя фильтра.
Кайзер
5

Имя шаблона хранится в таблице postmeta, поэтому все, что вам нужно сделать, это поместить это где-то в вашем цикле:

$template = get_post_meta( $post->ID, '_wp_page_template', true );
echo "Template: " . $template;
Саймон Блэкборн
источник
2
Да, я знаю об этом, но проблема в том, что он работает только тогда, когда страница имеет заданный шаблон. Прохладная вещь о коде я вывесил, что он расскажет вам , если текущая страница использует front-page.php, index.php, single.php, page.phpили любой другой файл. Ваш код отображает имя шаблона только для страниц с пользовательским шаблоном страницы.
chodorowicz
ах, извините - мое недопонимание вашего вопроса.
Саймон Блэкборн
@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()) { .... }для запуска вещи только на веб-интерфейс.

wyrfel
источник
Спасибо за предложение, они не решают проблему, но они направили меня к решению. Оказывается, что WP, генерируя список шаблонов, просматривает даже functions.phpнаходки "/Template Name:(.*)\n/siU"и таким образом обрабатывает functions.phpфайл как шаблон. Я думаю, что это ошибка WP, она даже не должна смотреть на этот файл. Решение: переместить файл в подкаталог.
chodorowicz
@chodorowicz: Это не ошибка в WP, это ошибка в вашей функции.
wyrfel
Поэтому в основном WP запрещает вам помещать строку «Имя шаблона» (даже в комментариях) в functions.phpфайл. Лично для меня это ошибка (небольшая, но в любом случае), но я думаю, что это вопрос обсуждения. Я думаю, вы не можете сказать, что сама функция глючит.
chodorowicz
WP не запрещает вам делать что-либо. Но WP также не обещает вам, что вы можете перебрать debug_backtrace (), чтобы выяснить, какой файл шаблона вы используете. То, что вы нашли его на форуме поддержки WP, не означает, что это официально поддерживаемый код. Как вы можете видеть, ваша функция явно исключает footer.php. Вы также можете добавить другое условие, исключающее functions.php. Кстати: ваша функция не ищет Template Nameв каждом из файлов, ваш цикл закончился задолго до этого.
wyrfel
Проблема была не в том, что debug_backtrace()я могу удалить весь код и просто уйти preg_match_all("/Template Name..., или даже просто, // Template Name:и WP обрабатывает его functions.phpкак файл шаблона, но спасибо за комментарии - это такая уникальная проблема, что, как вы говорите, нечестно сказать это ошибка Решение t31os является чистым и решает всю проблему. Здоровается.
chodorowicz
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в этой строке кода на: любое имя файла, из которого вам нужно отказаться.

если вам это нужно в админ-панели, используйте правильную привилегию (как можно раньше), чтобы убедиться, что в конце списка нет файлов . Например:

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

приоритет -5сделать так, чтобы он загружался первым. Ключ должен сделать эту линию в нужный момент.

Он не возвращает «текущий» шаблон-файл, но все текущие, используемые для текущей загрузки страницы. Может быть, "вырезать" с некоторой логикой из этой идеи .

get_included_files()«Последний» ключ последний зарегистрированный включаемый файл, Propably последний шаблон-файл / -часть используется в сноске на боковой панели виджетов или что - то. Вероятно, потому что несколько включенных файлов не перерегистрируются / заполняются снова в 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 );
Шафи
источник