Uzyskaj nazwę bieżącego pliku szablonu


57

Znalazłem to, aby wyświetlić bieżącą nazwę pliku używanego w szablonie:

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

Źródło: pobierz nazwę szablonu strony na stronie

Działa całkiem dobrze, z wyjątkiem tego, że w backend, w polu wyboru szablonu, otrzymuję ten brzydki dodatkowy wpis:

zrzut ekranu

Czy ktoś ma pomysł, jak to naprawić? Nie wiem nawet, dlaczego ta funkcja jest wywoływana w wewnętrznej bazie danych. Czy istnieje funkcja warunkowa typu is_frontend()- może to rozwiązałoby problem?


2
@chodorowicz - Chociaż zatrzymam się o krok od nazywania wyboru functions.phpjako błędu, całkowicie zgodzę się z twoją przesłanką. Co gorsza, zeskanowałem kod podstawowy WordPressa i znalazłem około 5 miejsc, w których mógł istnieć hak umożliwiający rozwiązanie tego problemu, ale nie znalazłem żadnego. Proponuję opublikować bilet na core.trac.wordpress.org .
— MikeSchinkel

@MikeSchinkel - dziękuję za komentarz, ale nie template_includezaczepia się, które sugeruje t31os, rozwiązać problem? A może źle cię zrozumiałem.
— chodorowicz

1
@MikeSchinkel - ma już łatkę :) core.trac.wordpress.org/ticket/16689
— chodorowicz

1
Stworzyłem nową wtyczkę, aby wyświetlić bieżący szablon. Sprawdź to na wordpress.org/extend/plugins/display-template-name

4
^ tj. wziąłeś kod z mojej odpowiedzi i umieściłeś go we wtyczce. I zrobiłeś to wszystko bez podania źródła pochodzenia, ani ja, ani
— wymiana stosów

Odpowiedzi:


68

Możesz ustawić zmienną globalną podczas template_includefiltrowania, a następnie sprawdzić, czy zmienna globalna jest możliwa do sprawdzenia, który szablon został uwzględniony.

Oczywiście nie chciałbyś mieć pełnej ścieżki wraz z plikiem, więc polecam skrócenie do nazwy pliku za pomocą basenamefunkcji PHP .

Przykładowy kod:
Dwie funkcje, jedna do ustawienia globalnej, druga do wywołania.

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

Następnie możesz wywoływać, get_current_templategdziekolwiek jest to potrzebne, w plikach motywu, zauważając, że naturalnie musi to nastąpić po uruchomieniu template_includeakcji (nie musisz się tym martwić, jeśli wywołanie zostanie wykonane w pliku szablonu).

W przypadku szablonów stron należy is_page_template()pamiętać, że pomoże to tylko w przypadku szablonów stron (znacznie mniej funkcji catch all ).

Informacje o zastosowanych lub wymienionych wyżej funkcjach:


Niesamowite! Wiedziałem, że musi być prostszy sposób.
— racl101

Jeden do dodania na początek mojej listy funkcji debugowania.
— Jules

23

najwyraźniej to wystarczy:

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

lub po prostu użyj go bezpośrednio w szablonie (mam tendencję do echa w footer.php w komentarzu HTML)

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

1
To nie zadziała z get-template-part tylko dlatego, że wiesz, pokazuje tylko single.php (na przykład), a nie plik, w którym się znajduje.
— m-torin

Tak, to prawda. Aby uzyskać nazwę dołączonego pliku, prawdopodobnie będziesz musiał użyć czegoś takiegoecho __FILE__;
— chodorowicz

jest to w porządku, na przykład w przypadku modyfikacji domyślnego szablonu bez przypisywania go do postu w backoffice. Na przykład za pomocą niestandardowych tras i filtra template_include. Dziękuję Ci.
— Luca Reghellin,

Jak mogę to zrobić w pętli? Próbuję wyprowadzić adres URL na jedną stronę każdego pliku szablonu.
— JacobTheDev

@JacobTheDev może używa echo __FILE__- ponieważ to nie zadziała, wyświetla tylko główny, początkowy szablon
— chodorowicz

17

Pomiędzy natywnymi funkcjami WP, takimi jak get_template_part (), a rodzimym PHP zawiera najbardziej niezawodny sposób, aby zobaczyć, że używane pliki motywu to pobranie listy wszystkich dołączonych plików i odfiltrowanie wszystkiego, co nie należy do motywu (lub motywów, gdy używana jest kombinacja nadrzędna i podrzędna) :

$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

Dodatek (więcej słodkiego kodu) do innych odpowiedzi tutaj.

Nazwa szablonu

Aby po prostu uzyskać nazwę bieżącego szablonu strony , użyj następującego wiersza.

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

Nazwa pliku

Aby po prostu powtórzyć nazwę bieżącego pliku szablonu , wykonaj następujące czynności

Edycja: Oto nowa wersja wtyczki zawarta w klasie. Pokazuje zarówno bieżącą nazwę pliku szablonu, jak i nazwę pliku hierarchii szablonów w haczyku zamykania u dołu strony.

Co mówi ci wtyczka:

  • Czy szablon pochodzi od rodzica motywu potomnego / bieżącego?
  • Czy szablon jest obsługiwany z podfolderu? Jeśli tak: poda ci nazwę
  • Nazwa pliku szablonu.

Wystarczy skopiować następujący kod do pliku i nazwać go wpse10537_template_info.php, załadować go do katalogu wtyczek i aktywować.

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

Wtyczka może również działać jako wtyczka MU.

Następnie możesz po prostu zadzwonić wpse10537_get_template_name()w dowolnym momencie (na przykład szablon motywu). Pozwala to uniknąć zaśmiecania globalnej przestrzeni nazw.


1
template_redirectnic nie przekazuje, myślę, że mylisz się template_include. Sprawdziłbym również, czy w filtrze zamiast wypełnienia statycznego var. Jeśli jakiś kod zdecyduje się uruchomić dodatkowy hak, może to zniszczyć.
— Rarst

@Rarst Done / Naprawiono. Dzięki za podpowiedź i wskazanie nazwy filtra.
— kaiser

5

Nazwa szablonu jest przechowywana w tabeli postmeta, więc wystarczy, że umieścisz ją gdzieś w pętli:

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

2
Tak, wiem o tym, ale problem polega na tym, że działa tylko wtedy, gdy strona ma ustawiony szablon. Świetną rzeczą kodu napisałem, że powie to, czy bieżąca strona używa front-page.php, index.php, single.php, page.phplub dowolny inny plik. Kod wyświetla nazwę szablonu tylko dla stron z niestandardowym szablonem strony.
— chodorowicz

ach, przepraszam - moje niezrozumienie twojego pytania.
— Simon Blackbourn

@ SimonBlackbourn To jest pomoc dla moich wymagań. Dzięki.
— KarSho,

3

Nie rozwiązuje to wszystkich pytań OP, ale poniższy kod jest z pewnością bardziej elegancki niż wyrażenia regularne i parsowanie samego pliku szablonu.

Jeśli jesteś na stronie, która korzysta z szablonu strony i chcesz uzyskać nazwę szablonu strony (tj. Czytelną dla człowieka nazwę zdefiniowaną w komentarzach u góry pliku PHP szablonu), możesz użyć ten mały samorodek:

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

Chciałem uzyskać nazwę szablonu, ponieważ miałem dość niemądrych nazw klas, które wbudowana body_classfunkcja WordPress tworzy podczas korzystania z szablonu. Na szczęście na samym końcu tej funkcji znajduje się haczyk filtrujący, który umożliwia dołączanie własnych nazw klas. Oto mój filtr. Mam nadzieję, że ktoś uzna to za przydatne:

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

Ten filtr weźmie wszystko, co nazwałeś szablonem strony, zastąpi spacje myślnikami i sprawi, że wszystko będzie pisane małymi literami, aby wyglądało jak wszystkie inne klasy WordPress.


0

Wystąpił problem z preg_match_alllinią. Spróbuj zamiast tego:

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

Możesz także używać if (!is_admin()) { .... }do uruchamiania rzeczy tylko w interfejsie użytkownika.


Dzięki za sugestie, nie rozwiązują problemu, ale kierują mnie w stronę rozwiązań. Okazuje się, że WP, generując listę szablonów, szuka nawet functions.phpznalezisk "/Template Name:(.*)\n/siU"i dlatego traktuje functions.phpplik jako szablon. Myślę, że to błąd WP, ​​nie powinien nawet patrzeć na ten plik. Rozwiązanie: przenieś plik do podkatalogu.
— chodorowicz

@chodorowicz: To nie jest błąd w WP, to błąd w twojej funkcji.
— wyrfel

Zasadniczo WP zabrania ci umieszczania w functions.phppliku ciągu „Nazwa szablonu:” (nawet w komentarzu) . Dla mnie osobiście jest to błąd (mały, ale w każdym razie), ale to chyba kwestia dyskusji. Myślę, że nie można powiedzieć, że sama funkcja jest błędna.
— chodorowicz

WP nie zabrania ci nic robić. Ale WP również nie obiecuje, że możesz zapętlić funkcję debug_backtrace (), aby dowiedzieć się, jakiego pliku szablonu używasz. To, że znalazłeś go na forum wsparcia WP, nie oznacza, że ​​jest to oficjalnie obsługiwany kod. Jak widać, twoja funkcja jawnie eksploruje footer.php. Równie dobrze możesz dodać kolejny warunek, który wyklucza functions.php. BTW: twoja funkcja nie szuka Template Namew każdym z plików, twoja pętla zakończyła się na długo przed tym.
— wyrfel

Problem nie polegał na tym debug_backtrace()- mogę usunąć cały kod i po prostu wyjść preg_match_all("/Template Name..., a nawet po prostu, // Template Name:a WP traktuje wtedy functions.phpjako plik szablonu, ale dziękuję za komentarze - jest to tak wyjątkowy problem, że, jak mówisz, nie jest fair powiedzieć to błąd. Rozwiązanie t31os jest czyste i rozwiązuje cały problem. Pozdrawiam
— chodorowicz

0

Graj razem z:

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

Napisane w:

Jak dowiedzieć się, która strona szablonu wyświetla bieżącą stronę?

jeśli admin-bar stuffścieżka jest wyświetlana u góry lub w innym pliku, zmień nazwę pliku template-loader.phpw tym wierszu kodu na: dowolną nazwę pliku, z której chcesz przerwać.

jeśli potrzebujesz tego na pasku administracyjnym, użyj odpowiedniego priorytetu (najwcześniej), aby mieć pewność, że żadne pliki nie zostaną wprowadzone na końcu tej listy. Na przykład:

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

priorytet -5upewnij się, że najpierw ładuje. Kluczem jest wyrenderowanie tej linii we właściwym momencie.

Nie zwraca „bieżącego” pliku szablonu, ale cały bieżący plik używany do bieżącego ładowania strony. Może „wyciąć” z logiką tego pomysłu .

Klawisz get_included_files()„ostatni” to ostatnio zarejestrowany dołączony plik, prawdopodobnie ostatni plik / część szablonu użyty w stopce przez widżet paska bocznego lub coś takiego. Prawdopodobnie pliki zawierające wiele plików nie rejestrują się ponownie / wypełniają ponownie w get_included_files ().

W przeciwnym razie zamiar włamania się do tego problemu musi być wyraźny . Dołączony plik nie może zgłosić się jako dołączony, dopóki nie zostanie dołączony . Potem jest prawdopodobnie za późno, aby wykorzystać scenariusz.

Przez większość czasu chciałbyś :

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

Ale nie jest to możliwe, jeśli szablon jest ładowany poza podstawową metodą Wordpress get_template_part. Zamiast tego przeprojektuj swoje potrzeby! Może loop_start(), in_the_loop()i add_action('the_post')ma rozwiązanie, które chcesz, aby zmienić dane w zależności od szablonu ów zamiar obciążenie dla każdego wpisu w pętli.


-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.