Ruft den Namen der aktuellen Vorlagendatei ab

57

Ich habe festgestellt, dass der aktuelle Name der in der Vorlage verwendeten Datei angezeigt wird:

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

Quelle: Name der Seitenvorlage auf einer Seite abrufen

Es funktioniert ganz gut, außer dass ich im Backend im Template-Auswahlfeld diesen hässlichen zusätzlichen Eintrag bekomme:

Bildschirmfoto

Hat jemand eine Idee, wie man das behebt? Ich weiß nicht einmal, warum diese Funktion im Backend aufgerufen wird. Gibt es eine bedingte Funktion wie is_frontend()- vielleicht würde dies das Problem lösen?

chodorowicz
quelle
2
@chodorowicz - Obwohl ich die Auswahl von nicht mehr functions.phpals Fehler bezeichne, stimme ich Ihrer Prämisse vollkommen zu. Um die Sache noch schlimmer zu machen, habe ich den WordPress-Kerncode gescannt und ungefähr 5 Stellen gefunden, an denen es einen Haken geben könnte, mit dem Sie dieses Problem lösen könnten, aber ich habe keinen gefunden. Ich würde vorschlagen, ein Ticket auf core.trac.wordpress.org zu veröffentlichen .
MikeSchinkel
@MikeSchinkel - danke für den Kommentar, aber template_includeHaken nicht , welche t31os vorgeschlagen, das Problem zu lösen? Oder vielleicht habe ich dich falsch verstanden.
Chodorowicz
1
@ MikeSchinkel - es hat bereits einen Patch :) core.trac.wordpress.org/ticket/16689
chodorowicz
1
Ich habe ein neues Plugin erstellt, um die aktuelle Vorlage anzuzeigen. Überprüfen Sie es auf wordpress.org/extend/plugins/display-template-name
4
^ ie. Sie haben den Code aus meiner Antwort genommen und in ein Plugin eingepackt. Und Sie haben das alles getan, ohne den Ursprung zu würdigen, weder mich noch den WP-Stack-Austausch ... nett ...: /
t31os

Antworten:

68

Sie können während des template_includeFilters eine globale Variable festlegen und später die globale Variable überprüfen, um festzustellen, welche Vorlage enthalten ist.

Sie möchten natürlich nicht den vollständigen Pfad zusammen mit der Datei, also würde ich empfehlen, mit der PHP- basenameFunktion auf den Dateinamen zu kürzen .

Beispielcode:
Zwei Funktionen, eine zum Festlegen der globalen, eine zum Aufrufen.

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

Sie können dann jederzeit in den Designdateien darauf zugreifen. get_current_templateBeachten Sie, dass dies natürlich nach dem Auslösen der template_includeAktion erfolgen muss (Sie müssen sich darüber keine Gedanken machen, wenn der Aufruf in einer Vorlagendatei erfolgt).

Für Seitenvorlagen gibt es is_page_template()unter Berücksichtigung, dass nur bei Seitenvorlagen geholfen wird (eine weitaus geringere Catch-All- Funktion).

Informationen zu den oben verwendeten oder referenzierten Funktionen:

t31os
quelle
Genial! Ich wusste, dass es einen einfacheren Weg geben musste.
racl101
Eine, die am Anfang meiner Liste der Debugging-Funktionen steht.
Jules
22

anscheinend ist das genug:

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

oder benutze es einfach direkt in der Vorlage (ich neige dazu, in der footer.php im HTML-Kommentar zu echo)

<?php global $template; echo basename($template); ?>
chodorowicz
quelle
1
Das funktioniert nicht mit get-template-part, nur damit du weißt, es zeigt nur single.php (zum Beispiel) und nicht die Datei, in der es sich befindet.
m-torin
Ja, es ist wahr. Um den Namen der enthaltenen Datei zu erhalten, müssten Sie wahrscheinlich so etwas verwendenecho __FILE__;
chodorowicz
Dies ist in Ordnung, wenn Sie beispielsweise die Standardvorlage ändern, ohne sie einem Beitrag im Backoffice zuzuweisen. Zum Beispiel mit benutzerdefinierten Routen und dem Filter template_include. Danke.
Luca Reghellin
Wie kann ich das in einer Schleife machen? Ich versuche, die URL auf einer Seite jeder Vorlagendatei auszugeben.
JacobTheDev
@JacobTheDev vielleicht mit echo __FILE__- weil dies nicht funktioniert, zeigt es nur Haupt, erste Vorlage
Chodorowicz
17

Zwischen nativen WP-Funktionen wie get_template_part () und den nativen PHP- Funktionen besteht die zuverlässigste Methode zum Anzeigen der verwendeten Themendateien darin, eine Liste aller enthaltenen Dateien abzurufen und herauszufiltern, was nicht zum Thema gehört (oder Themen, wenn übergeordnete und untergeordnete Kombination verwendet wird). :

$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
quelle
9

Ein Zusatz (süßer Code) zu anderen Antworten hier.

Vorlagenname

Verwenden Sie die folgende Zeile, um nur den Namen der aktuellen Seitenvorlage abzurufen .

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

Dateiname

Wenn Sie nur den Namen der aktuellen Vorlagendatei wiedergeben möchten , gehen Sie wie folgt vor

Bearbeiten: Hier ist die neue Version des Plugins, die in einer Klasse zusammengefasst ist. Es werden sowohl der Name der aktuellen Vorlagendatei als auch der Name der Vorlagendateihierarchie im Shutdown-Hook am unteren Rand der Seite angezeigt.

Was das Plugin Ihnen sagt:

  • Ist die Vorlage vom Elternteil des Kindes / aktuelles Thema?
  • Wird die Vorlage aus einem Unterordner geliefert? Wenn ja: Sagt Ihnen den Namen
  • Der Name der Vorlagendatei.

Kopieren Sie einfach den folgenden Code in eine Datei und benennen Sie ihn wpse10537_template_info.php, laden Sie ihn in Ihr Plugins-Verzeichnis hoch und aktivieren Sie ihn.

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

Dieses Plugin kann auch als MU-Plugin ausgeführt werden.

Sie können dann einfach wpse10537_get_template_name()an beliebiger Stelle anrufen (zB in einer Themenvorlage). Dadurch wird vermieden, dass der globale Namespace überladen wird.

Kaiser
quelle
1
template_redirectpassiert nichts, ich denke, Sie sind verwirrend mit template_include. Ich würde auch prüfen, ob im Filter, anstatt ob statische var gefüllt ist. Wenn ein Code entscheidet, Hook zusätzliche Zeit auszuführen, kann dies die Dinge ruinieren.
Rarst
@Rarst Fertig / Behoben. Danke für den Hinweis und den Hinweis auf den Filternamen.
Kaiser
5

Der Name der Vorlage wird in der Postmeta-Tabelle gespeichert. Sie müssen also nur Folgendes in Ihre Schleife einfügen:

$template = get_post_meta( $post->ID, '_wp_page_template', true );
echo "Template: " . $template;
Simon Blackbourn
quelle
2
Ja, ich weiß darüber Bescheid, aber das Problem ist, dass es nur funktioniert, wenn eine Seite eine festgelegte Vorlage hat. Die kühle Sache über den Code , den ich geschrieben ist , dass es wird Ihnen sagen , wenn die aktuelle Seite verwendet front-page.php, index.php, single.php, page.phpoder jede andere Datei. In Ihrem Code wird der Vorlagenname nur für Seiten mit einer benutzerdefinierten Seitenvorlage angezeigt.
Chodorowicz
Oh, Entschuldigung - mein Missverständnis Ihrer Frage.
Simon Blackbourn
@ SimonBlackbourn Es ist Hilfe für meine Anforderung. Vielen Dank.
KarSho
3

Damit werden nicht alle Fragen des OP beantwortet, aber der folgende Code ist sicherlich eleganter als reguläre Ausdrücke und analysiert die Vorlagendatei selbst.

Wenn Sie sich auf einer Seite befinden, die eine Seitenvorlage verwendet, und den Namen der Seitenvorlage abrufen möchten (dh den lesbaren Namen, den Sie in den Kommentaren oben in Ihrer PHP-Vorlagendatei definiert haben), können Sie ihn verwenden dieses kleine Nugget:

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

Ich wollte den Vorlagennamen haben, weil ich die albern-langweiligen Klassennamen satt hatte, die die integrierte WordPress- body_classFunktion erstellt, wenn Sie eine Vorlage verwenden. Zum Glück befindet sich ganz am Ende dieser Funktion ein Filter-Hook, mit dem Sie auch Ihre eigenen Klassennamen anhängen können. Hier ist mein Filter. Hoffe, jemand findet es nützlich:

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

Dieser Filter nimmt alles, was Sie als Seitenvorlage bezeichnet haben, auf, ersetzt Leerzeichen durch Bindestriche und macht alles in Kleinbuchstaben, so dass es aussieht wie alle anderen WordPress-Klassen.

Tom Auger
quelle
0

Es gibt ein Problem mit der preg_match_allLeitung. Versuchen Sie dies stattdessen:

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

Außerdem können Sie if (!is_admin()) { .... }Dinge nur auf dem Frontend ausführen.

Wyrfel
quelle
Vielen Dank für den Vorschlag, sie lösen das Problem nicht, aber sie haben mich irgendwie zu Lösungen geführt. Es hat sich herausgestellt, dass WP beim Generieren der Vorlagenliste sogar nach den functions.phpFunden sucht "/Template Name:(.*)\n/siU"und somit die functions.phpDatei als Vorlage behandelt . Ich denke, das ist ein WP-Fehler, es sollte sich nicht einmal diese Datei ansehen. Die Lösung: Verschieben Sie die Datei in das Unterverzeichnis.
Chodorowicz
@chodorowicz: Das ist kein Fehler in WP, es ist ein Fehler in Ihrer Funktion.
Wyrfel
WP verbietet Ihnen also grundsätzlich, den String "Template Name:" (auch in Kommentaren) in die functions.phpDatei einzufügen. Für mich persönlich ist das ein Fehler (klein, aber trotzdem), aber ich nehme an, das steht zur Diskussion. Ich denke, man kann nicht sagen, dass die Funktion selbst fehlerhaft ist.
Chodorowicz
WP verbietet dir nichts zu tun. Aber WP verspricht Ihnen auch nicht, dass Sie eine Schleife über debug_backtrace () durchführen können, um herauszufinden, welche Vorlagendatei Sie verwenden. Nur weil Sie es in einem WP-Supportforum gefunden haben, heißt das nicht, dass es offiziell unterstützten Code enthält. Wie Sie vielleicht sehen, explodiert Ihre Funktion die Datei footer.php explizit. Sie können auch eine andere Bedingung hinzufügen, die functions.php ausschließt. Übrigens: Ihre Funktion sucht nicht Template Namein jeder Datei, Ihre Schleife ist schon lange zu Ende.
Wyrfel
Das Problem war nicht mit debug_backtrace()- ich kann den gesamten Code entfernen und einfach verlassen preg_match_all("/Template Name..., oder auch nur // Template Name:und WP behandelt dann functions.phpals Vorlagendatei, aber danke für Kommentare - dies ist ein so einzigartiges Problem, dass es, wie Sie sagen, nicht fair zu sagen ist Es ist ein Fehler. Die t31os-Lösung ist sauber und löst das gesamte Problem. Grüße
Chodorowicz
0

Spielen Sie mit:

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

Geschrieben am:

Wie finden Sie heraus, welche Vorlagenseite die aktuelle Seite enthält?

Wenn der admin-bar stuffPfad oben template-loader.phpangezeigt wird oder eine andere Datei, ändern Sie den Dateinamen in dieser Codezeile in: den Dateinamen , von dem Sie abbrechen müssen.

Wenn Sie dies in der Admin-Leiste benötigen, verwenden Sie die richtige Priorität (frühestens) , um sicherzustellen, dass am Ende dieser Liste keine Dateien eingegeben werden . Zum Beispiel:

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

Priorität -5stellen Sie sicher, dass es zuerst geladen wird. Der Schlüssel ist, diese Linie im richtigen Moment zu rendern.

Es wird nicht die "aktuelle" Vorlagendatei zurückgegeben, sondern die gesamte aktuell für das aktuelle Laden der Seite verwendete. Vielleicht mit etwas Logik aus dieser Idee "rausgeschnitten" .

Der get_included_files()"letzte" Schlüssel ist die zuletzt registrierte eingeschlossene Datei, wahrscheinlich die letzte Schablonendatei / der letzte Teil, der in der Fußzeile vom Seitenleisten-Widget oder so verwendet wird. Möglicherweise werden in get_included_files () in cos mutiple enthaltene Dateien nicht erneut registriert / ausgefüllt.

Andernfalls muss die Absicht klar sein, dieses Problem zu lösen . Es gibt keine Möglichkeit für eine eingeschlossene Datei, sich selbst als eingeschlossen zu melden, bis sie eingeschlossen wurde . Dann ist es wahrscheinlich zu spät, das Szenario zu verwenden.

Die meiste Zeit möchten Sie :

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

Dies ist jedoch nicht möglich, wenn die Vorlage außerhalb der Wordpress- Kernmethode von geladen wird get_template_part. Entwerfen Sie stattdessen Ihre Bedürfnisse neu! Vielleicht loop_start(), in_the_loop()und add_action('the_post')hat die Lösung , die Sie mögen, Daten von Vorlage abhängig das sind für jeden Eintrag in einer Schleife Gonna Last zu verändern.

Jonas Lundman
quelle
-3
global $post;
$templateName = get_page_template_slug( $post->ID );
//echo $templateName;
var_dump( $templateName );
Shafi
quelle