Lấy tên của tệp mẫu hiện tại


57

Tôi đã tìm thấy điều này để hiển thị tên hiện tại của tệp được sử dụng trong mẫu:

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

Nguồn: lấy tên của mẫu trang trên một trang

Nó hoạt động khá tốt, ngoại trừ trong phần phụ trợ, trong hộp chọn mẫu, tôi nhận được mục nhập thêm xấu xí này:

ảnh chụp màn hình

Có ai có bất cứ ý tưởng làm thế nào để sửa chữa nó? Tôi thậm chí không biết tại sao chức năng này được gọi trong phần phụ trợ. Có một chức năng có điều kiện như is_frontend()- có lẽ điều này sẽ giải quyết vấn đề?


2
@chodorowicz - Mặc dù tôi sẽ dừng một bước ngắn khi gọi việc lựa chọn functions.phplà một lỗi, tôi sẽ hoàn toàn đồng ý với tiền đề của bạn. Để làm cho vấn đề tồi tệ hơn, tôi đã quét mã lõi WordPress và tìm thấy khoảng 5 nơi có thể có một cái móc để cho phép bạn xử lý vấn đề này nhưng tôi không tìm thấy. Tôi khuyên bạn nên đăng một vé trên core.trac.wordpress.org .
MikeSchinkel

@MikeSchinkel - cảm ơn bạn đã bình luận, nhưng không template_includehook, mà t31os đã đề xuất, giải quyết vấn đề? Hoặc có thể tôi đã hiểu lầm bạn.
chodorowicz

1
@MikeSchinkel - nó đã có bản vá :) core.trac.wordpress.org/ticket/16689
chodorowicz

1
Tôi đã tạo một plugin mới để hiển thị mẫu hiện tại. Kiểm tra nó trên wordpress.org/extend/plugins/display-template-name

4
^ tức là bạn lấy mã từ câu trả lời của tôi và gói nó vào một plugin. Và bạn đã làm tất cả những điều đó mà không cung cấp bất kỳ khoản tín dụng nào cho nguồn gốc, cả bản thân tôi và WP stackexchange ... thật tuyệt ...: /
t31os 30/03/2016

Câu trả lời:


68

Bạn có thể đặt biến toàn cục trong template_includebộ lọc và sau đó kiểm tra xem toàn cầu có thể xem mẫu nào đã được đưa vào không.

Bạn tự nhiên sẽ không muốn đường dẫn hoàn chỉnh cùng với tệp, vì vậy tôi khuyên bạn nên cắt bớt tên tệp bằng basenamehàm PHP .

Mã ví dụ:
Hai hàm, một để đặt toàn cục, một để gọi nó.

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

Sau đó, bạn có thể gọi get_current_templatebất cứ nơi nào bạn cần trong tệp chủ đề, lưu ý điều này cần xảy ra một cách tự nhiên sau khi template_includehành động được thực hiện (bạn sẽ không cần phải lo lắng về điều này nếu cuộc gọi được thực hiện trong tệp mẫu).

Đối với các mẫu trang có is_page_template(), hãy nhớ rằng sẽ chỉ giúp trong trường hợp các mẫu trang (ít bắt được tất cả các chức năng).

Thông tin về các chức năng được sử dụng hoặc được tham chiếu ở trên:


Tuyệt vời! Tôi biết phải có một cách đơn giản hơn.
racl101

Một để thêm vào đầu danh sách chức năng sửa lỗi của tôi.
Jules

23

rõ ràng điều này là đủ:

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

hoặc chỉ sử dụng nó trực tiếp trong mẫu (Tôi có xu hướng lặp lại trong footer.php trong nhận xét HTML)

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

1
Điều đó sẽ không hoạt động với phần get-template chỉ để bạn biết, nó chỉ hiển thị single.php (ví dụ) chứ không phải tệp trong đó.
m-torin

Vâng đúng vậy. Để có được tên của tệp được bao gồm, có lẽ bạn cần phải sử dụng một cái gì đó như thế nàyecho __FILE__;
chodorowicz

điều này là tốt, ví dụ trong trường hợp khi bạn sửa đổi mẫu mặc định mà không gán nó cho một bài đăng ở backoffice. Ví dụ: sử dụng các tuyến tùy chỉnh và bộ lọc template_include. Cảm ơn bạn.
Luca Reghellin

Làm thế nào tôi có thể làm điều này trong một vòng lặp? Tôi đang cố gắng xuất URL tới một trang của mỗi tệp mẫu.
JacobTheDev

@JacobTheDev có thể sử dụng echo __FILE__- vì điều này sẽ không hoạt động, nó chỉ hiển thị mẫu chính, ban đầu
chodorowicz

17

Giữa các hàm WP gốc như get_template_part () và bản gốc của PHP bao gồm cách đáng tin cậy nhất để xem các tệp của chủ đề được sử dụng là tìm nạp danh sách tất cả các tệp được bao gồm và lọc ra bất cứ thứ gì không thuộc chủ đề (hoặc chủ đề khi sử dụng kết hợp cha và con) :

$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

Một bổ sung (mã ngọt ngào hơn) cho câu trả lời khác ở đây.

Tên mẫu

Để chỉ lấy tên mẫu trang hiện tại , hãy sử dụng dòng sau.

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

Tên tệp

Khi bạn chỉ muốn lặp lại tên tệp mẫu hiện tại , hãy làm như sau

Chỉnh sửa: Đây là phiên bản mới của plugin được gói trong một lớp. Nó hiển thị cả tên tệp mẫu hiện tại, cũng như tên tệp phân cấp mẫu trong móc tắt máy ở cuối trang.

Những gì plugin nói với bạn:

  • Là mẫu từ cha mẹ của chủ đề trẻ em / hiện tại?
  • Là mẫu được phục vụ từ một thư mục con? Nếu có: Cho bạn biết tên
  • Tên tệp mẫu.

Chỉ cần sao chép mã sau vào một tệp và đặt tên cho nó wpse10537_template_info.php, tải nó lên thư mục plugin của bạn và kích hoạt nó.

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

Plugin này cũng có thể chạy như MU-Plugin.

Sau đó, bạn có thể chỉ cần gọi wpse10537_get_template_name()tại bất kỳ điểm nào (ví dụ như một mẫu chủ đề). Điều này tránh làm lộn xộn không gian tên toàn cầu.


1
template_redirectkhông vượt qua bất cứ điều gì, tôi nghĩ rằng bạn đang nhầm lẫn với template_include. Ngoài ra, tôi sẽ kiểm tra xem bên trong bộ lọc thay vì nếu var tĩnh được điền. Nếu một số mã quyết định chạy hook thêm thời gian, nó có thể phá hỏng mọi thứ.
Rarst

@Rarst Xong / Đã sửa. Cảm ơn gợi ý và chỉ ra tên bộ lọc.
kaiser

5

Tên mẫu được lưu trữ trong bảng postmeta, vì vậy tất cả những gì bạn cần làm là đặt cái này ở đâu đó trong vòng lặp của bạn:

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

2
Vâng, tôi biết về điều này, nhưng vấn đề là nó chỉ hoạt động khi một trang có một mẫu được thiết lập. Điều thú vị về mã tôi đăng là nó sẽ cho bạn biết nếu trang hiện đang sử dụng front-page.php, index.php, single.php, page.phphoặc bất kỳ tập tin khác. Mã của bạn chỉ hiển thị tên mẫu cho các trang có mẫu trang tùy chỉnh.
chodorowicz

ah, xin lỗi - sự hiểu lầm của tôi về câu hỏi của bạn.
Simon Blackbourn

@SimonBlackbourn Đó là sự giúp đỡ cho yêu cầu của tôi. Cảm ơn.
KarSho

3

Điều này không giải quyết tất cả các câu hỏi của OP, nhưng đoạn mã dưới đây chắc chắn thanh lịch hơn các biểu thức thông thường và phân tích chính tệp mẫu.

Nếu bạn đang ở trên Trang đang sử dụng Mẫu trang và bạn muốn lấy Tên của mẫu trang (tức là: tên người có thể đọc được mà bạn đã xác định trong các nhận xét ở đầu tệp PHP mẫu của bạn), bạn có thể sử dụng con nhỏ này:

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

Tôi muốn lấy tên mẫu vì tôi thực sự phát ốm với các tên lớp dài ngớ ngẩn mà body_classchức năng WordPress tích hợp tạo ra khi bạn sử dụng một mẫu. May mắn thay, có một móc lọc ở cuối hàm đó để cho phép bạn thêm tên lớp của riêng bạn. Đây là bộ lọc của tôi. Hy vọng ai đó thấy nó hữu ích:

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

Bộ lọc này sẽ lấy bất cứ thứ gì bạn đặt tên cho mẫu trang của bạn, thay thế dấu cách bằng dấu gạch ngang và làm cho mọi thứ trở nên thấp hơn để nó trông giống như tất cả các lớp WordPress khác.


0

Có một vấn đề với preg_match_alldòng. Hãy thử điều này thay thế:

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

Ngoài ra, bạn chỉ có thể sử dụng if (!is_admin()) { .... }để chạy mọi thứ trên frontend.


Cảm ơn vì lời đề nghị, họ không giải quyết vấn đề, nhưng họ đã hướng tôi vào giải pháp. Nó chỉ ra rằng WP, trong khi tạo ra danh sách các mẫu, đang tìm kiếm thậm chí vào functions.phptìm "/Template Name:(.*)\n/siU"và do đó xử lý các functions.phptập tin như mẫu. Tôi nghĩ đây là lỗi WP, thậm chí không nên xem tập tin này. Giải pháp: di chuyển tệp vào thư mục con.
chodorowicz

@chodorowicz: Đó không phải là lỗi trong WP, đó là lỗi trong chức năng của bạn.
wyrfel

Vì vậy, về cơ bản WP cấm bạn đặt chuỗi "Tên mẫu:" (ngay cả trong nhận xét) trong functions.phptệp. Đối với cá nhân tôi, đó là một lỗi, (dù nhỏ, nhưng dù sao) nhưng đó là điều cần bàn luận, tôi cho là vậy. Tôi nghĩ rằng bạn không thể nói rằng chính chức năng là lỗi.
chodorowicz

WP không cấm bạn làm bất cứ điều gì. Nhưng WP cũng không hứa với bạn rằng bạn có thể lặp qua debug_backtrace () để tìm hiểu tệp mẫu nào bạn đang sử dụng. Chỉ vì bạn tìm thấy nó trên một diễn đàn hỗ trợ WP không có nghĩa là mã được hỗ trợ chính thức. Như bạn có thể thấy, chức năng của bạn khám phá rõ ràng footer.php. Bạn cũng có thể thêm một điều kiện khác loại trừ hàm.php. BTW: chức năng của bạn không tìm kiếm Template Nametrong mỗi tệp, vòng lặp của bạn đã kết thúc từ lâu trước đó.
wyrfel

Vấn đề không nằm ở debug_backtrace()- tôi có thể xóa tất cả mã và chỉ để lại preg_match_all("/Template Name..., hoặc thậm chí chỉ // Template Name:và WP coi đó functions.phplà tệp mẫu, nhưng cảm ơn vì đã nhận xét - đây là một vấn đề độc đáo mà như bạn nói, thật không công bằng khi nói đó là một lỗi giải pháp t31os là sạch sẽ và giải quyết toàn bộ vấn đề. Greets.
chodorowicz

0

Chơi cùng với:

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

Viết tại:

Làm thế nào để bạn tìm ra trang mẫu nào đang phục vụ trang hiện tại?

nếu admin-bar stuffđường dẫn hiển thị ở trên cùng hoặc bất kỳ tệp nào khác, hãy thay đổi tên tệp template-loader.phptrong dòng mã này thành: bất kỳ tên tệp nào bạn cần ngắt.

nếu bạn cần điều này trong thanh quản trị, hãy sử dụng quyền ưu tiên (sớm nhất) để làm cho shure không có tệp nào được nhập vào cuối danh sách này. Ví dụ:

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

ưu tiên -5làm cho shure nó tải đầu tiên. Điều quan trọng là kết xuất dòng này vào đúng thời điểm.

Nó không trả về tệp mẫu "hiện tại", nhưng tất cả hiện tại được sử dụng cho tải trang hiện tại. Có thể "cắt ra" với một số logic từ ý tưởng đó .

Khóa get_included_files()"cuối cùng" là tệp được bao gồm đăng ký cuối cùng, có thể là tệp / tệp mẫu cuối cùng được sử dụng trong phần chân trang bởi tiện ích thanh bên hoặc một cái gì đó. Có thể cho phép, cos mutipl bao gồm các tệp không đăng ký lại / cư trú lại trong get_included_files ().

Nếu không, cường độ phải rõ ràng để hack vấn đề này . Không có cách nào để một tệp được bao gồm tự báo cáo như được bao gồm, cho đến khi nó được đưa vào . Sau đó, nó có thể đến muộn để sử dụng kịch bản.

Hầu hết "thời gian" bạn muốn :

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

Nhưng điều đó là không thể nếu mẫu được tải bên ngoài phương thức cốt lõi của Wordpress get_template_part. Thiết kế lại nhu cầu của bạn thay vào đó! Có thể loop_start(), in_the_loop()add_action('the_post')có giải pháp bạn muốn, để thay đổi dữ liệu tùy thuộc vào mẫu sẽ tải cho mỗi mục trong một vòng lặp.


-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.