Check if current term is a child of another term

I’m attempting to make an archive template that will apply only to subcategories of a particular term. My structure looks something like this:

  • Events (main taxonomy)
    • Tradeshow
      • Show subcat 1
      • Show subcat 2
    • Other taxonomies

I want Show subcat 1 and Show subcat 2 (and any other subcategories) to all get the same archive template. This is one of my attempts at it, which is definitely not working. Here’s the code from my functions.php.

    add_filter( 'template_include', 'kd_event_subcategory_archive' );

    function kd_event_subcategory_archive( $template ) {
        $term = get_queried_object()->term_id;
        if ( $term->parent == 'tradeshow' ) {
            $event_subcat = locate_template( 'taxonomy-tradeshow-subcategory.php' );

            return $event_subcat;
        }

        return $template;
    }

I can’t seem to figure out how to properly check if a term is the child of my tradeshow term.

2 Answers
2

There are two problems that have thwarted your check:

    $term = get_queried_object()->term_id;
    if ( $term->parent == 'tradeshow' ) {

Starting with:

    $term = get_queried_object()->term_id;

Here $term contains the ID of a term, not a term object. Lets assume this is term number 5, the result is:

    $term = 5;
    if ( $term->parent == 'tradeshow' ) {

Which won’t work. $term is a number, not an object, so you cant do ->parent on it.

The fix is to just use the queried object directly:

    $term = get_queried_object();

Which leads us to the next problem:

    if ( $term->parent == 'tradeshow' ) {

The parent isn’t a string, it’s a term ID. 0 if there is no parent, else it’s the ID of the parent term, as shown if we look up WP_Term:

/**
 * ID of a term's parent term.
 *
 * @since 4.4.0
 * @var int
 */
public $parent = 0;

So you need to acquire the tradeshow term in advance to find out its ID. Usually, for these scenarios, developers will not hardcode the slug, but instead provide a setting that lists terms, and store the ID as an option to avoid this kind of lookup, and increase flexibility

But in this case you can use the get_term_by function, e.g.

$tradeshow = get_term_by('slug', 'tradeshow', 'events')

Then using:

$tradeshow->term_id === $term->parent

Problems and Advice

These are additional items I wanted to mention that are unrelated

Debugging

Using var_dump, a debugger, or some other tool to see what the contents of $term was would have revealed these problems.

Additionally, PHP error logs will be full of warnings and notices pointing at the if statement for trying to do the equivalent of 5->parent which makes no sense to PHP. Pay attention to error logs. I’d recommend using the query monitor plugin as an easy way to catch unexpected warnings

The Queried object isn’t always a term

This code will run on every page load:

add_filter( 'template_include', 'kd_event_subcategory_archive' );

function kd_event_subcategory_archive( $template ) {
    $term = get_queried_object()->term_id;
    if ( $term->parent == 'tradeshow' ) {

But what if the user visits a date archive or an author archive? Now the code runs anyway, generating errors. So this filter needs tests to check if the user is on a taxonomy archive, and that the taxonomy matches.

It may even be a singular post, and if the trade show term has a term ID of 5, and you’re on the post or page with ID 5, then you’ll get a post showing on a taxonomy archive.

I suspect though that it would be easier to use a separate taxonomy.

https://codex.wordpress.org/Function_Reference/get_queried_object

  • if you’re on a single post, it will return the post object
  • if you’re on a page, it will return the page object
  • if you’re on an archive page, it will return the post type object
  • if you’re on a category archive, it will return the category object
  • if you’re on an author archive, it will return the author object
  • etc.

Leave a Comment