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

26 февр. 2011 г., 17:47:14
Просмотры: 155K
Голосов: 81

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

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 = '(по умолчанию)' ; }
    $template_file = array_pop(explode('/themes/', basename($template_file)));
    return $template_file . ' > '. $template_name ;
}

Источник: получить имя шаблона страницы на странице

Это работает довольно хорошо, за исключением того, что в панели администратора, в поле выбора шаблона, я получаю эту некрасивую дополнительную запись:

Скриншот выпадающего списка шаблонов в панели администратора WordPress

Есть ли у кого-нибудь идеи, как это исправить? Я даже не знаю, почему эта функция вызывается в панели администратора. Существует ли условная функция типа is_frontend() - возможно, это решило бы проблему?

9
Комментарии

@chodorowicz - Хотя я остановлюсь в шаге от того, чтобы назвать выбор functions.php ошибкой, я полностью согласен с вашей предпосылкой. Чтобы усугубить ситуацию, я просканировал код ядра WordPress и нашел около 5 мест, где мог бы быть хук, позволяющий вам обработать эту проблему, но не нашел ни одного. Я бы предложил создать тикет на http://core.trac.wordpress.org.

MikeSchinkel MikeSchinkel
26 февр. 2011 г. 22:13:34

@MikeSchinkel - спасибо за комментарий, но разве хук template_include, который предложил t31os, не решает проблему? Или, возможно, я вас неправильно понял.

chodorowicz chodorowicz
27 февр. 2011 г. 17:29:35

@chodorowicz - Теперь вы меня совсем запутали. Ответ @t31os решает проблему, которая сильно отличается от той, которую, как я понял, вы задавали, основываясь на вашем вопросе и последующих комментариях к другим ответам. Но если ответ @t31os решил вашу реальную потребность, то моя путаница здесь не важна, так как ваш вопрос был отвечен.

MikeSchinkel MikeSchinkel
27 февр. 2011 г. 18:21:23

Да, фактическая необходимость заключалась в отображении имени используемого файла темы. Код, который я опубликовал, имел недостаток (который можно решить, вынеся функцию за пределы основной папки темы), но решение @t31os гораздо более чистое и удовлетворяет потребность. Однако, если я правильно вас понимаю, реальная проблема (WordPress не должен пытаться читать functions.php как файл шаблона страницы) всё ещё сохраняется. Я попробую опубликовать это на trac, пока этого не сделал. Привет!

chodorowicz chodorowicz
27 февр. 2011 г. 18:44:34

@MikeSchinkel - для этого уже есть патч :) http://core.trac.wordpress.org/ticket/16689

chodorowicz chodorowicz
28 февр. 2011 г. 19:33:19

@chodorowicz - Да, мой комментарий касался реальной проблемы: предотвращения попыток WordPress читать functions.php и/или предоставления возможности написать хук для изменения возвращаемого значения. Рад, что вы нашли патч, а не создали дубликат; так сложно найти существующие тикеты.

MikeSchinkel MikeSchinkel
28 февр. 2011 г. 20:57:16

Я создал новый плагин для отображения текущего шаблона. Посмотрите его на http://wordpress.org/extend/plugins/display-template-name/

User User
1 июн. 2012 г. 14:32:12

^ Т.е. вы взяли код из моего ответа и обернули его в плагин. И сделали всё это без указания первоисточника — ни меня, ни WP stackexchange... отлично... :/

t31os t31os
31 мар. 2014 г. 00:08:14

Похожий вопрос: https://wordpress.stackexchange.com/questions/253820/how-to-use-if-is-page-template

Jesse Nickles Jesse Nickles
17 авг. 2023 г. 13:36:24
Показать остальные 4 комментариев
Все ответы на вопрос 9
3
80

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

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

27 февр. 2011 г. 02:40:03
Комментарии

Отлично! Я знал, что должен быть более простой способ.

racl101 racl101
9 мар. 2013 г. 00:11:02

Добавлю это в начало своего списка функций для отладки.

Jules Jules
17 июл. 2013 г. 00:41:27

Также пользователям может быть полезно узнать о встроенных функциях is_single, is_attachment, is_singular, is_page и других is_... функциях.

Fabien Snauwaert Fabien Snauwaert
7 апр. 2022 г. 10:22:03
5
46

похоже, этого достаточно:

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

или можно использовать напрямую в шаблоне (я обычно вывожу в footer.php в HTML-комментарии)

<?php global $template; echo basename($template); ?>
9 апр. 2011 г. 19:25:16
Комментарии

Для вашего сведения, с get-template-part это не сработает, он показывает только single.php (например), а не файл, в котором он находится.

MTT MTT
25 сент. 2012 г. 18:11:09

Да, это верно. Чтобы получить имя включаемого файла, вам, вероятно, нужно использовать что-то вроде этого echo __FILE__;

chodorowicz chodorowicz
5 окт. 2012 г. 15:25:39

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

Luca Reghellin Luca Reghellin
15 сент. 2016 г. 13:05:23

Как я могу сделать это в цикле? Я пытаюсь вывести URL для одной страницы каждого файла шаблона.

JacobTheDev JacobTheDev
28 февр. 2017 г. 17:07:22

@JacobTheDev возможно, используя echo __FILE__ - потому что это не сработает, отображается только основной, первоначальный шаблон

chodorowicz chodorowicz
8 мар. 2017 г. 00:08:06
0
18

Между нативными функциями WordPress, такими как get_template_part(), и нативными include в 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 );
1 мар. 2013 г. 20:27:00
2
12

Дополнение (ещё больше полезного кода) к другим ответам здесь.

Имя шаблона

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

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

Имя файла

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

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

Что показывает плагин:

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

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

<?php
/** Plugin Name: (#10537) »kaiser« Получить имя файла шаблона */

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(
                 "Файл шаблона"
                ,basename( $file )
            );
            return $file;
        }

        // Возвращаем статическую переменную при вызове вне фильтра
        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( "Шаблон", $slug );

        $this->to_stack(
             "Подпапка"
            ,strstr( $slug, "/", true )
        );

        $this->to_stack(
             "Шаблон (в подпапке)"
            ,str_replace( "/", "", strstr( $slug, "/" ) )
        );
    }

    public function is_parent_template()
    {
        if ( ! is_null( wp_get_theme()->parent ) )
            return $this->to_stack( 'из родительской темы' );

        $this->to_stack( 'из текущей/дочерней темы' );
    }

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

} // endif;

Этот плагин также может работать как MU-Plugin.

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

8 сент. 2012 г. 05:16:18
Комментарии

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

Rarst Rarst
15 сент. 2012 г. 20:42:16

@Rarst Сделано/Исправлено. Спасибо за подсказку и указание правильного имени фильтра.

kaiser kaiser
15 сент. 2012 г. 22:18:02
3

Название шаблона хранится в таблице postmeta, поэтому вам достаточно добавить следующий код в ваш цикл:

$template = get_post_meta( $post->ID, '_wp_page_template', true );
echo "Шаблон: " . $template;
26 февр. 2011 г. 19:51:28
Комментарии

Да, я знаю об этом, но проблема в том, что это работает только когда у страницы задан шаблон. Крутая особенность кода, который я опубликовал, в том, что он покажет, использует ли текущая страница front-page.php, index.php, single.php, page.php или любой другой файл. Ваш код отображает имя шаблона только для страниц с пользовательским шаблоном страницы.

chodorowicz chodorowicz
26 февр. 2011 г. 20:05:17

Ах, извините — я неправильно понял ваш вопрос.

Simon Blackbourn Simon Blackbourn
26 февр. 2011 г. 20:23:54

@SimonBlackbourn Это помогло в моей задаче. Спасибо.

KarSho KarSho
8 окт. 2013 г. 10:04:02
0

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

Если вы находитесь на Странице, которая использует Шаблон страницы, и хотите получить название шаблона страницы (то есть читаемое имя, которое вы определили в комментариях в начале вашего 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];
}

Я хотел получить название шаблона, потому что был очень утомлен длинными и неудобными названиями классов, которые встроенная функция WordPress body_class создает при использовании шаблона. К счастью, в самом конце этой функции есть фильтр, позволяющий добавлять свои собственные имена классов. Вот мой фильтр. Надеюсь, кто-то найдет его полезным:

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.

1 мая 2013 г. 04:56:21
5

Есть проблема со строкой preg_match_all. Попробуйте такой вариант:

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

Также вы можете использовать if (!is_admin()) { .... } для выполнения кода только на фронтенде.

26 февр. 2011 г. 18:43:26
Комментарии

Спасибо за предложения, они не решают проблему, но в некотором роде направили меня к решениям. Оказывается, WP при генерации списка шаблонов заглядывает даже в functions.php, находит там "/Template Name:(.*)\n/siU" и поэтому рассматривает functions.php как файл шаблона. Я считаю, что это баг в WP — он вообще не должен заглядывать в этот файл. Решение: переместить файл в поддиректорию.

chodorowicz chodorowicz
26 февр. 2011 г. 19:33:30

@chodorowicz: Это не баг в WP, это баг в вашей функции.

wyrfel wyrfel
26 февр. 2011 г. 20:18:54

По сути, WP запрещает вам использовать строку "Template Name:" (даже в комментариях) в файле functions.php. Лично для меня это баг (небольшой, но всё же), но это, пожалуй, вопрос дискуссионный. Не думаю, что можно сказать, что сама функция содержит ошибку.

chodorowicz chodorowicz
26 февр. 2011 г. 21:14:01

WP не запрещает вам делать что-либо. Но WP также не обещает, что вы можете перебирать debug_backtrace(), чтобы узнать, какой файл шаблона используете. Тот факт, что вы нашли это на форуме поддержки WP, не означает, что это официально поддерживаемый код. Как вы можете видеть, ваша функция явно исключает footer.php. Вы также можете добавить условие, исключающее functions.php. Кстати: ваша функция не ищет Template Name в каждом из файлов, ваш цикл завершился задолго до этого.

wyrfel wyrfel
27 февр. 2011 г. 08:00:12

Проблема была не в debug_backtrace() — я могу удалить весь код и оставить только preg_match_all("/Template Name..., или даже просто // Template Name:, и WP всё равно будет рассматривать functions.php как файл шаблона. Но спасибо за комментарии — это настолько уникальная проблема, что, как вы говорите, несправедливо называть это ошибкой. Решение t31os чистое и полностью решает проблему. Привет.

chodorowicz chodorowicz
27 февр. 2011 г. 13:56:31
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() — это последний зарегистрированный включенный файл, вероятно, последний файл шаблона/часть, используемая в футере виджетом сайдбара или чем-то подобным. Вероятно, потому что множественные включенные файлы не перерегистрируются/не добавляются снова в 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') содержат решение, которое вам нужно, для изменения данных в зависимости от шаблона, который будет загружаться для каждой записи в цикле.

15 сент. 2017 г. 09:49:57
0
-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
17 февр. 2016 г. 10:54:16