Получить имя текущего файла шаблона
Я нашел этот код для отображения текущего имени файла, используемого в шаблоне:
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 ;
}
Источник: получить имя шаблона страницы на странице
Это работает довольно хорошо, за исключением того, что в панели администратора, в поле выбора шаблона, я получаю эту некрасивую дополнительную запись:
Есть ли у кого-нибудь идеи, как это исправить? Я даже не знаю, почему эта функция вызывается в панели администратора. Существует ли условная функция типа is_frontend()
- возможно, это решило бы проблему?

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

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

похоже, этого достаточно:
add_action('wp_head', 'show_template');
function show_template() {
global $template;
echo basename($template);
}
или можно использовать напрямую в шаблоне (я обычно вывожу в footer.php в HTML-комментарии)
<?php global $template; echo basename($template); ?>

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

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

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

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

Между нативными функциями 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 );

Дополнение (ещё больше полезного кода) к другим ответам здесь.
Имя шаблона
Чтобы просто получить название текущего шаблона страницы, используйте следующую строку.
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( " – ", $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()
в любом месте (например, в шаблоне темы). Это позволит избежать загрязнения глобального пространства имён.

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

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

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

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

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

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

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

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