Gibt es eine Variable für einen Namen eines Vorlagenteils?

8

Wenn Sie eine Vorlage mit get_template_part()(oder locate_template()) aufgerufen haben, können Sie feststellen , in welcher Vorlage Sie sich befinden.

Zum Beispiel , wenn Sie anrufen get_template_part('loop','archive');ausarchive.php

und arbeiten dann in Ihrer Datei loop-archive.php. gibt es eine Möglichkeit , eine Variable zu definieren, die den Namen des aktuellen Schablonenteil hat .... so $template = 'loop-archive'. Besser noch, vielleicht in zwei Teilen, also 'Schleife' und 'Archiv', aber ich kann das mit etwas String-Splitting machen.

Frage # 10537 scheint Art von verwandten , aber scheint nicht zu Cover - Vorlage Teilen .

Helgatheviking
quelle

Antworten:

2

Es gibt keine globale Kernvariable, die den aktuellen Kontext zurückgibt. Sie können jedoch Ihre eigenen Tags mit kontextbezogenen Vorlagen erstellen . Sie können die bedingten Tags in derselben Reihenfolge wie der WordPress-Kern durchlaufen, indem Sie folgen wp-includes/template-loader.php.

Wickeln Sie Ihre Ausgabe einfach in eine benutzerdefinierte Designfunktion. So mache ich das (Hinweis: Ich glaube nicht, dass ich template-loader.php genau befolge):

function oenology_get_context() {

    $context = 'index';

    if ( is_home() ) {
        // Blog Posts Index
        $context = 'home';
        if ( is_front_page() ) {
            // Front Page
            $context = 'front-page';
        } 
    }else if ( is_date() ) {
        // Date Archive Index
        $context = 'date';
    } else if ( is_author() ) {
        // Author Archive Index
        $context = 'author';
    } else if ( is_category() ) {
        // Category Archive Index
        $context = 'category';
    } else if ( is_tag() ) {
        // Tag Archive Index
        $context = 'tag';
    } else if ( is_tax() ) {
        // Taxonomy Archive Index
        $context = 'taxonomy';
    } else if ( is_archive() ) {
        // Archive Index
        $context = 'archive';
    } else if ( is_search() ) {
        // Search Results Page
        $context = 'search';
    } else if ( is_404() ) {
        // Error 404 Page
        $context = '404';
    } else if ( is_attachment() ) {
        // Attachment Page
        $context = 'attachment';
    } else if ( is_single() ) {
        // Single Blog Post
        $context = 'single';
    } else if ( is_page() ) {
        // Static Page
        $context = 'page';
    }

    return $context;
}

Dann übergebe ich einfach oenology_get_context()als Parameter, zB:

get_template_part( 'loop', oenology_get_context() );

Ich denke, etwas in dieser Richtung wäre ein guter Kandidat für den Kern, obwohl ich nicht sicher bin, wie ich es am besten umsetzen kann. Ich würde jedoch gerne einen Patch einreichen.

Chip Bennett
quelle
Wow Chip. das ist sehr, sehr schlau. und Ihr Anwendungsfall ist genau das, was ich beabsichtigt hatte. Was einen Patch angeht, warum sollten Sie dieses globale Recht nicht einfach registrieren, während Sie den Template Loader durchlaufen?
Helgatheviking
1
Weil ich nicht sicher bin, ob das Hinzufügen eines weiteren globalen Ansatzes der "gesegnete" Ansatz für den Kern wäre. Wahrscheinlich wäre eine Funktion, die den Kontext als Zeichenfolge zurückgibt, besser - aber das würde wahrscheinlich ein wenig Umschreiben erfordern template-loader.php.
Chip Bennett
Schön +1. Nur eine Anmerkung: indexwürde niemals übereinstimmen, entweder is_front_page()oder is_home()würde auslösen.
Kaiser
1
Eine andere Sache: is_home()sollte an erster Stelle stehen, da sie auch dann zurückgibt front-page, wenn die Einstellung "Letzter Beitrag" aktiviert ist und keine Titelseite vorhanden ist. Gerade getestet.
Kaiser
Stimmen Sie mit @kaiser überein. Sie können sogar verwenden is_home() && 'page', je nach den Anforderungen. Weitere Informationen zu Blogposts und statischen Seiten auf der Startseite finden Sie in meiner eigenen Antwort hier: wordpress.stackexchange.com/questions/208503/… . Übrigens, @Chip und @helgatheviking, es wäre besser, a switchanstelle von so vielen zu verwenden elseif(es ist effizienter ;-). Grüße!
Gerard
4

ein bisschen wie ein Gesichtspalme, weil die Antwort in reinem PHP ist

$path_parts = pathinfo(__FILE__);
//var_dump($path_parts); 
echo $path_parts['filename'];
Helgatheviking
quelle
2

Wenn Sie sich den Quellcode der get_template_partFunktion ansehen , sehen Sie:

function get_template_part( $slug, $name = null ) {
    do_action( "get_template_part_{$slug}", $slug, $name );

    $templates = array();
    if ( isset($name) )
        $templates[] = "{$slug}-{$name}.php";

    $templates[] = "{$slug}.php";

    locate_template($templates, true, false);
}

Es wird ein Array mit 2 Vorlagennamen erstellt: {$slug}-{$name}.phpund {$slug}.phpund wird verwendet load_template, um die Vorlagendatei zu finden und einzuschließen (der zweite Parameter ist true, dh diese Datei einschließen).

Sie können diese Funktion nachahmen, um den Pfad der Vorlagendatei zurückzugeben, anstatt ihn einzuschließen:

function my_get_template_part( $slug, $name = null, $include = false ) {
    do_action( "get_template_part_{$slug}", $slug, $name );

    $templates = array();
    if ( isset($name) )
        $templates[] = "{$slug}-{$name}.php";

    $templates[] = "{$slug}.php";

    return locate_template($templates, $include, false);
}

Verwendungszweck:

// Don't load the template
$template = my_get_template_part( 'loop', 'archive', false );

// Or load the template
$template = my_get_template_part( 'loop', 'archive', true );

// Get the file name only
$template = basename( $template );

// Without .php extension
$template = substr( $template, 0, -4 );

Sie können mehr damit spielen $template, um das zu bekommen, was Sie wollen.

Anh Tran
quelle
das ist ziemlich ordentlich! +1 sicher, aber ich musste die $ template info in der loop-arhive.php Vorlage kennen (um deinem Beispiel zu folgen)
helgatheviking
Sie können eine globale Variable verwenden, die in festgelegt ist archive.php, und sie inloop-archive.php
Anh Tran
2

Listen Sie alle Bedingungen auf, die sind true

Da alle is_*()Funktionen in einer Abfragevariablen gleichwertig sind (die Funktionen sind nur Wrapper), können Sie auch auf andere Weise darauf zugreifen: Holen Sie sich einfach alle, die es sind true.

Ich habe ein Ticket auf core / trac geschrieben , das eine Funktion hinzufügt, um sie alle aufzulisten .

In der Zwischenzeit können Sie beide aufgelisteten Funktionen als Hilfs-Plugins verwenden, die Ihnen zeigen, auf welche Anfrage welche Bedingung verfügbar ist. Es wird ein var_dump()unter der Fußzeile (sowohl admin als auch public) am shutdownHaken gedruckt .

<?php
/** Plugin Name: (#62232) »kaiser« List all conditionals that are true */
function get_conditionals()
{ 
    global $wp_query; 

    foreach ( get_object_vars( $wp_query ) as $is_key => $is_value ) 
    { 
            if ( $is_value && preg_match( "/is_/", $is_key ) ) 
                    $conditionals[] = $is_key; 
    } 

    return var_dump( $conditionals );
} 
add_action( 'shutdown', 'get_conditionals' );

Auf diese Weise können Sie sie einfach durchlaufen.

@scribu hat dem Ticket seine eigene Funktion hinzugefügt (auch eine interessante Lösung).

   

<?php
/** Plugin Name: (#62232) »scribu« List all conditionals that are true */
function get_query_flags( $wp_query = null ) {
    if ( !$wp_query )
        $wp_query = $GLOBALS['wp_query'];

    $flags = array();

    foreach ( get_object_vars( $wp_query ) as $key => $val ) {
        if ( 'is_' == substr( $key, 0, 3 ) && $val )
            $flags[] = substr( $key, 3 );
    }

    return var_dump( $flags );
}
add_action( 'shutdown', 'get_query_flags' );

Performance

Ich habe einen Leistungstest für jede Funktion in der Mitte einer Vorlage mit ausgeführt timer_start/*_stop();. Um fair zu sein, habe ich alle Funktionen in einen Namen mit einem Zeichen umbenannt a/b/c().

Wie Sie sehen können, ist die fest codierte Funktion von Chips am schnellsten, dann geht sie an meine und zuletzt ist in diesem Fall Scribus.

Geben Sie hier die Bildbeschreibung ein

Aktualisieren

Wenn Sie mich kennen, dann kennen Sie meine Liebe zu Iteratoren wegen ihrer Eleganz, Klarheit und ihrer Fähigkeit, nur ein einzelnes Element im Speicher zu halten, anstatt ein ganzes Array während des Loopings zu kopieren. Hier ist also eine schnelle benutzerdefinierte Klasse, die a erweitert \FilterIteratorund daher nur eine einzige Methode überarbeitet.

<?php

namespace WPSE;

class ConditionalsFilter extends \FilterIterator
{
    /**
     * Accepts properties that start with `is_` and have a positive boolean value
     * @return bool
     */
    public function accept()
    {
        return 0 === strncasecmp( $this->key(), 'is_', 3 )
            and filter_var(
                $this->current(),
                FILTER_VALIDATE_BOOLEAN,
                FILTER_NULL_ON_FAILURE
            );
    }
}

Es kann recht einfach verwendet werden. Der $it->current()enthält den Wert, während $it->key()der Bedingungs- / Eigenschaftsname zurückgegeben wird.

$cond = new WPSE\ConditionalsFilter( new \ArrayIterator(
    get_object_vars( $GLOBALS['wp_query'] )
) );
foreach ( $cond as $c )
{
    var_dump(
        $cond->key(),
        $cond->current()
    );
}
Kaiser
quelle
1
Nun, das ist sehr klug. Vielen Dank! Ich muss das noch einmal besuchen, wenn ich mit einigen anderen Dingen fertig bin, an denen ich arbeite. Es ist auch sehr schwer, sich daran zu erinnern, Kapital zu schlagen! Schlechte Gewohnheiten sind schwer zu brechen.
Helgatheviking