Check if a custom taxonomy archive page is being displayed

You hava a lot of issues here:

  • pre_get_posts is not the correct hook to set templates. pre_get_posts are used to alter the ain query query vars just before the SQL are build to run the main query’s query

  • A filter should always return something. Not doing this will have unexpected behavior, and forgetting about this can have you on a wild goose chase for hours debugging the issue.

  • Using globals to control theme features or to store any kind of data is bad practice and not very safe coding. WordPress has already made such a huge mess of globals, particularly naming conventions. Just check how newbies (that does not know WordPress) unknowingly use variable like $post and $posts as local variables. These are native globals uses by WordPress, and using them as local variables breaks the values of these globals.

    Because of this, something on the page goes wrong, there are no errors, so you are stuck on a wild goose chase trying to debug something that you have unknowingly broke. Globals are pure evil and you should avoid using them. Just think, if you use the variable $wpgo_global_column_layout for the query arguments of a custom query, you will break the value of the template that needs to be set, your template does not load because the value of $wpgo_global_column_layout are not recognized as a valid template name, you are stuffed and don’t know why your template does not load as your code are 100% that should load a custom template

  • is_tax() is the wrong check to use to check whether a post has a certain term or not, is_tax() simply checks if you are on a taxonomy archive or not. You should be using has_term() which do just that, checks if a certain post has a certain term

  • If you need to set a template for a taxonomy page, single_template is the wrong hook, you should be using the taxonomy_template hook or the more generic template_include filter

  • In the line $post->post_type == 'advert' || is_tax( 'advert_category' ), I suspect you are using the wrong operator. You should be using the AND operator. I’m not going to explain this here as I already done something similar here. Note that, with the current setup, whenever you are viewing a post from the post type advert, your condition will return true and fire whether or not the second condition (is_tax( 'advert_category' )) fails.

  • If you need to target a term according to parent_child order, you simply need to check the term object’s $parent property. A value of 0 means the term is a parent, any other value means that the term is a child/grandchild/grand-grandchild/etc term

Lets drop the crappy globals and set the templates properly. I do not know how your theme exactly sets templates through the $wpgo_global_column_layout, but the following should work with priority. I have commented the code to make it easy to follow

FOR SINGLE PAGES:

add_filter( 'single_template', function ( $template )
{
    // Remove all filters from the current filter
    remove_all_filters( current_filter(), PHP_INT_MAX );
    
    /**
     * Get the current single post object. We will use get_queried_object
     * as it is safer to use as $post
     *
     * @see https://wordpress.stackexchange.com/q/167706/31545
     */
    $current_post = get_queried_object();
    
    // Check if the current post belongs to the advert post type, if not, bail
    if ( $current_post->post_type !== 'advert' )
        return $template;
    
    // Get the post terms
    $terms = get_the_terms( 
        $current_post, // Current post object
        'advert_category' // Taxonomy name
    );
    
    // If $terms are empty or throws a WP_Error object, bail
    if ( !$terms || is_wp_error( $terms ) )
        return $template
    
    /**
     * Get the first term and check if it is a top level term or not.
     * Load template according to parent value
     *
     * NOTE, this only work correctly if the post has one term only
     */
    if ( $terms[0]->parent == 0 ) {
        $part="single-parent.php"; // Set the template to use for parent terms
    } else {
        $part="single-child.php"; // Set the child term template
    }
    
    // Check if the template exists, if not bail
    $locate_template = locate_template( $part );
    if ( !$locate_template ) 
        return $template;
    
    // We have reached this point, set our custom template
    return $template = $locate_template;
}, PHP_INT_MAX + 1 );

FOR TAXONOMY PAGES:

add_filter( 'taxonomy_template', function ( $template )
{
    // Remove all filters from the current filter
    remove_all_filters( current_filter(), PHP_INT_MAX );

    // Get the current term object. We will use get_queried_object
    $current_term = get_queried_object();
    
    // If the current term does not belong to advert post type, bail
    if ( $current_term->taxonomy !== 'advert_category' )
        return $template;
    
    // Check if the term is top level or not and set template accordingly
    if ( $current_term->parent == 0 ) {
        $part="taxonomy-parent.php"; // Set the template to use for parent terms
    } else {
        $part="taxonomy-child.php"; // Set the child term template
    }
    
    // Check if the template exists, if not bail
    $locate_template = locate_template( $part );
    if ( !$locate_template ) 
        return $template;
    
    // We have reached this point, set our custom template
    return $template = $locate_template;
}, PHP_INT_MAX + 1 );

Just one note, all the code is untested, so make sure to test it locally first with debug set to true. Also modify and abuse the code to suit your needs

Leave a Comment