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?

chodorowicz
źródło
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:

t31os
źródło
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); ?>
chodorowicz
źródło
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 );
Rarst
źródło
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.

kajzer
źródło
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;
Simon Blackbourn
źródło
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.

Tom Auger
źródło
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.

wyrfel
źródło
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.

Jonas Lundman
źródło
-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
Shafi
źródło