4

Is there a way to use different templates for different levels within a hierarchical taxonomy, specified by filename. I know about taxonomy-taxonomyname.php and taxonomy-taxonomyname-term.php templates. Looking for a more generic "per taxonomy level" based method.

So, a taxonomy named Earth might contain:

  1. Africa
    • Cameroon
    • Congo
    • Senegal
  2. Asia
    • Japan
    • Korea
  3. Europe
    • Greece
    • ...
  4. South America
  5. ...

Is there a way to have one template for Africa, Asia, Europe and South America (earth-numbers-level.php)... and another template for Cameroon, Congo, Japan, Greece... (earth-bullets-level.php)?

Looking over a few different template hierarchy docs, I'm guessing not. If that's true, what's the best/most efficient way to differentiate taxonomy levels within taxonomy-earth.php so that I might use different template parts for each?

5

+1ed Pieter Goosen's answer, but this time I want to be the one who advocate the "make it simple" way.

In your taxonomy-earth.php template, you can check if the queried term as a parent, and require another template if so.

If you ask this question, I guess you already have (or wish to create) 2 templates, let's call them:

  • taxonomy-earth-continent.php
  • taxonomy-earth-country.php

In your taxonomy-earth.php file you can:

<?php
$slug = 'taxonomy-earth';
// default to continent
$name = 'continent';

// maybe set specific template to "country" if queried term has a parent
$term = get_queried_object();
if ( is_object( $term ) && ! empty( $term->parent ) )
    $name = 'country';

get_template_part( $slug, $name );

These 6 lines of template code, will be enough to require a different template for "child" terms.

Thanks to the use of get_template_part the template code is also child-theme friendly and triggers an hook: get_template_part_taxonomy-earth that can be used to do things when the template is required.

  • Your approach is definitely better if you are going to use the same child term template across all child terms, which will be actually the way to go. My approach is just when you need a specific template per child term ;-) – Pieter Goosen Nov 23 '15 at 15:40
  • @PieterGoosen change the line $name = 'country'; to $name = $term->slug and you get specific template per child term :) – gmazzap Nov 23 '15 at 15:51
  • Aaahhhgggg crap yes, missed that ;-) – Pieter Goosen Nov 23 '15 at 15:52
  • This is a much cleaner version of what I went with (based off of learning stuff from @PieterGoosen's answer). Time to delete some code. Thank you! – Will Nov 23 '15 at 18:00
  • @Will I agree with this answer being "cleaner" than mine, over-thought this a bit, ;-). Enjoy – Pieter Goosen Nov 23 '15 at 18:11
5

You have a couple of options here:

taxonomy-{$taxonomy}-{$term->parent}-{$term}.php

We can create our own hierarchy (or actually extends the existing hierarchy) by creating our own taxonomy-{$taxonomy}-{$term->parent}-{$term}.php template for use when a child term is being viewed. We will also make use of the taxonomy_template filter to add our new taxonomy templates to the hierarchy so that they will be used.

You can try something like the following: (NOTE: All code is untested and all code is commented for easy following and understanding. The code also assumes that top level terms already have a taxonomy-{$taxonomy}-{$term}.php template.)

add_filter( 'taxonomy_template', function ( $template )
{
    // Get the current term object being viewed
    $current_term = get_queried_object();

    // We can restrict this to a single taxonomy, for example
    // if ( $current_term->taxonomy !== 'my_taxonomy' )
        // return $template;

    /**
     * Check if current term is top level, if so, return the default $template which
     * should be template taxonomy-{$taxonomy}-{$term}.php if found
     */
    if ( $current_term->parent == 0 ) // Top level terms have parent of 0
        return $template;

    // We made it to here, so the term is not top level

    // We need to get the top level term of the current term
    $hierarchy = get_ancestors( $current_term->term_id, $current_term->taxonomy );
    // The parent ID will always be the last ID in the array returned by get_ancestors
    $parent_ID = end( $hierarchy );
    // Now we can get the top level term object
    $top_level_term = get_term_by( 'id', $parent_ID, $current_term->taxonomy );

    /** 
     * Lets build our custom template name, add subfolder name if template
     * is in a subfolder, for example /subfolder/name-of-template.php
     */
    $custom_template = 'taxonomy-{$current_term->taxonomy}-{$top_level_term->slug}-{$current_term->slug}.php';
    // Check if our custom template exist, if not, return default $template
    $locate_template = locate_template( $custom_template );
    if ( !$locate_template )
        return $template;

    // Finally, everything checked out, return our custom template
    return $template = $locate_template;
}); 

You can adjust the code as needed

Custom template parts

You can create your taxonomy-{$taxonomy}-{$term}.php template and the make use of template parts inside your loop to include template parts according to child term. The best here will be to write a custom function and then calling that function inside the loop (or wherever you need it) instead of get_template_part()

For this to work, we need to call our template part as follow:

  • top level terms will be {$term}.php, like africa.php

  • child terms will be {$term->parent}-{$term}.php like africa-cameroon.php

  • default/fallback template like content.php. Just remember not to pass the .php part of the template name to the function

Here is the code

/** 
 * Function to set template parts according to child term
 *
 * @param (string) $default Default template part to use like content.php
 * @return $template
 */
function get_custom_template_part( $default = '' )
{
    // Check if we have a value for $default, if not, return false
    if ( !$default )
        return false;

    // Sanitize the $default value
    $default = filter_var( $default, FILTER_SANITIZE_STRING );

    // Check if we are on a taxonomy page, if not, return the $default template
    if ( !is_tax() )
        return get_template_part( $default );

    // Get the current term being viewed
    $current_term = get_queried_object();

    /**
     * Set our custom variables
     * $top_level_term will hold the top level term object
     * $part will hold the current term slug if the current term is not top level
     */
    $top_level_term = '';
    $part = '';

    // Check if current term is top level, if not, get the top level parent
    if ( $current_term->parent != 0 ) {
        // We need to get the top level term of the current term
        $hierarchy = get_ancestors( $current_term->term_id, $current_term->taxonomy );
        // The parent ID will always be the last ID in the array returned by get_ancestors
        $parent_ID = end( $hierarchy );
        // Now we can get the top level term object
        $top_level_term = get_term_by( 'id', $parent_ID, $current_term->taxonomy );
        $part = $current_term->slug;
    }

    // We now will set our template's name accordingly
    if ( $top_level_term ) {
        $name = $top_level_term->slug;
    } else {
        $name = $current_term->slug;
    }

    // We will now check if our template parts exist, if not, return our default
    if ( $part ) { // This means we have a child term
        $template = get_template_part( $name, $part );
    } else { // This means top level term
        $template = get_template_part( $name );
    }

    if ( $template )
        return $template;

    return get_template_part( $default );
}

You can extend this as needed, and you can also add your template parts in a subfolder, and then just append the subfolder name to the value of $name inside the function

You can now use the function in the following way in your taxonomy-{$taxonomy}-{$term}.php or taxonomy-{$taxonomy}.php template

Default template: content.php

get_custom_template_part( 'content' );
  • Thank you so much! I learned an incredible amount about WordPress from this. I wound up doing something based on your second idea but add_filter( 'taxonomy_template') is a genuine revelation. I had no idea about that filter. – Will Nov 23 '15 at 18:02
  • My pleasure, glad you found my post useful in some way :-). Enjoy and good luck with your project – Pieter Goosen Nov 23 '15 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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