9

One you have called a template with get_template_part() (or locate_template()) is there a way to know what template you are in.

For example if you call get_template_part('loop','archive'); from archive.php

and then are working in your loop-archive.php file. is there a way to define a variable that has the name of the current template part.... so $template = 'loop-archive'. better still, maybe in two parts so 'loop' and 'archive' but I can do that with some string splitting.

Question #10537 seems sort of related but doesn't seem to cover template parts.

4 Answers 4

3

There isn't a core global variable that returns the current context. However, you can construct your own, using contextual template conditional tags. You can step through the conditional tags in the same order as WordPress core, by following wp-includes/template-loader.php.

Simply wrap your output in a custom Theme function. Here's how I do it (note: I don't think I strictly follow template-loader.php):

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

Then, I just pass oenology_get_context() as a parameter, e.g.:

get_template_part( 'loop', oenology_get_context() );

I think something along these lines would be a good candidate for core, though I'm not sure the best way to implement. I'd love to submit a patch, though.

5
  • wow chip. that's very, very slick. and your use case is exactly what i was intending. as far as a patch, why wouldn't you just register this global right at the same time you are stepping through template loader? Commented Aug 23, 2012 at 3:16
  • 1
    Because I'm not sure if adding another global would be the "blessed" approach for core. Probably a function that returns context as a string would be better - but then, that would probably require a bit of a rewrite to template-loader.php. Commented Aug 23, 2012 at 11:09
  • Nice +1. Just one note: index would never match, as either is_front_page() or is_home() would trigger.
    – kaiser
    Commented Sep 17, 2012 at 12:21
  • 1
    Another thing: is_home() should be first, as it gives back front-page even when the "latest post" setting is activated and no front-page is present. Just tested.
    – kaiser
    Commented Oct 2, 2012 at 10:52
  • Agree with @kaiser. You can even use is_home() && 'page', depending on the needs. For a more extensive information about Blog Posts vs Static Page in the Front Page, take a look at my own answer, here: wordpress.stackexchange.com/questions/208503/…. BTW, @Chip and @helgatheviking, it'd be better to use use a switch instead of so many elseif (it's more efficient ;-). Regards!
    – Unix
    Commented Nov 25, 2015 at 17:47
4

bit of a facepalm, because the answer is in pure PHP

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

If you look at the source code of get_template_part function, you'll see:

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

It creates an array of 2 template names: {$slug}-{$name}.php and {$slug}.php and use load_template to find the template file and include it (the 2nd parameter is true, which means include that file).

You can mimic this function to return the template file path instead of include it, like:

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

Usage:

// 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 );

You can play more with $template to get what you want.

2
  • that's pretty neat! +1 for sure, but i needed to know the $template info inside the loop-arhive.php template (to follow your example) Commented Aug 22, 2012 at 1:39
  • You can use a global variable which is set in archive.php, and reuse it in loop-archive.php
    – Anh Tran
    Commented Aug 22, 2012 at 16:36
2

List all conditionals that are true

As all is_*() functions have their equivalent in a query variable (the functions are just wrappers), you can access them also another way: Get simply all that are true.

I wrote a ticket on core/trac that adds a function to list them all.

In the meanwhile you can use both listed functions as helper plugins that show you on which request which conditional is available. It will print a var_dump() below the footer (both admin & public) at the shutdown hook.

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

This way you can simply loop through them.

@scribu added his own function to the ticket (an interesting solution too).

   

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

I ran a performance test on each function in the middle of a template using timer_start/*_stop();. TO be fair, I renamed all functions to a one character name a/b/c().

As you can see, Chips hard coded function is fastest, then goes mine and last is in this case scribus.

enter image description here

Update

If you know me, then you know my love for iterators for their elegance, clearness and their ability to hold only a single item in memory instead of of copy of a whole array while looping. So here's a quick custom class that extends a \FilterIterator, therefore needing only a single method reworked.

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

It can be used quite easily. The $it->current() holds the value, while $it->key() returns the conditional/property name.

$cond = new WPSE\ConditionalsFilter( new \ArrayIterator(
    get_object_vars( $GLOBALS['wp_query'] )
) );
foreach ( $cond as $c )
{
    var_dump(
        $cond->key(),
        $cond->current()
    );
}
2
  • 1
    Well that is very clever. Thanks! I'll have to re-visit this when I get done with some of the other things I am working. Also, it is really hard to remember to capitalize! Bad habits are tough to break. Commented Sep 8, 2012 at 1:30
  • @kaiser - Why call the function at shutdown and not earlier in the process? Secondly, the function outputs the result as array(2) { [0]=> string(7) "is_home" [1]=> string(13) "is_posts_page" }. Have I understood it correctly that is_home is the parent conditional and it encapsulates is_posts_page? If yes, I assume it is safe to perform a conditional check limited to just is_home rather than is_home && is_posts_page`?
    – Motivated
    Commented Nov 26, 2020 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.