How to create a theme template for the taxonomy “root”

Here’s an alternative based on a single taxonomy.php file.

In summary, call a function at the beginning of taxonomy.php. The function evaluates the taxonomy url and identifies which custom taxonomy (if any) applies. It then gets ALL the terms for that taxonomy (not just the one in the url), and then gets ALL the posts referenced by those terms. At this point, you add the code to format the custom taxonomy posts however you wish OR (if there are no Custom Taxonomy posts) you let the taxonomy.php take over and format the posts as per usual. In my (tested) example, the function goes into functions.php but you could put it in a plugin if you prefer.

I created two custom taxonomies (‘color‘ and ‘location‘). For the sale of testing, I have hard coded theses into an array in the function, but there are a host of alternatives to this approach. My intention was to show that this could be done programatically, and without creating the proverbial ‘101 taxonomy files’.

I created taxonomy.php by creating a blank file, saving it as ‘taxonomy.php and then copying the contents of archive.php. In my test, I only printed the title for the term posts (to prove that the post information had been retrieved) but you can change this to whatever you wish.

In the screen snapshot you can see that the url is “location/sydney”. The standard taxonomy page shows the two “Sydney” posts at the bottom of the screen, but the function includes one extra post (shown at the top of the page) for location=”Melbourne”.

My array of custom taxonomies (my variable is called $myarrayoptions) has only two custom taxonomies (the slugs are ‘color’ and ‘location’) but this can be as may as you like. I made one assumption: that there was only one custom taxonomy per post. Again, there are ways of dealing with multiple taxonomies per post, but this will suffice for demonstration purposes.

This is my function in functions.php. I’ve left in all my ‘echo’ statements for debugging – you can delete those at your leisure.

/*
 * Create function to set if custom taxonomy is set
*/
function checktax(){
    global $wp;
    //echo "<p>TESTING - START</p>";

    // create a simple array showing the name of all the referenced custom taxonomies
    $myarrayoptions = array('color','location');
    //echo "the custom taxonomies are <pre>";print_r($myarrayoptions);echo "</pre>";  //DEBUG

    // get the url
    $myurl = home_url( $wp->request );
    //echo "<p>The url is ".$myurl." </p>";  //DEBUG

    // Explode the url to get access to the taxonomy and terms
    $pageterms = explode("https://wordpress.stackexchange.com/", $myurl);
    //echo "the exploded components of the URL <pre>";print_r($pageterms);echo "</pre>"; //DEBUG

    // check whether any custom taxonomies are included in the page url and then do stuff
    if (array_intersect($pageterms,$myarrayoptions)) {

        // find which custom taxonomy is in the url - there should only be ONE!
        $result = array_intersect($pageterms,$myarrayoptions);
        //echo "the custom taxonomy is <pre>";print_r($result);echo "</pre>"; //DEBUG

        // get the value of the custom taxonomy. this is very clumsy but it does work.
        foreach ($result as $key => $value){
        //echo "<p>the array key is ".$key." and the taxonomy is ".$value."</p>";  //DEBUG
        }
        // echo "<p>the taxonomy is ".$value."</p>"; //DEBUG

        // the term in the URL is the field after the taxonomy so we just add 1 to the key to get the term
        $urlterm = $pageterms[($key+1)];
        //echo "<p>the term in the url is ".$urlterm."</p>"; //DEBUG

        // get all the terms for this custom taxonomy
        $myterms = get_terms( array(
                'taxonomy' => $value,
                'hide_empty' => false,
        ) );    
        //echo "the terms are <pre>";print_r($myterms);echo "</pre>"; //DEBUG

        //create a simple array to store the terms for use in a query
        $termsarray = []; 
        // get the slugs only
        $termsarray = wp_list_pluck( $myterms, 'slug' );
        //echo "terms array is <pre>";print_r($termsarray);echo "</pre>"; //DEBUG

        // build a new query to get all the posts for the custom taxonomy
        // this is sortable but the OP didn't mention that
        $myargs = array(
                'post_type' => 'post',
                'posts_per_page' => -1,
                'tax_query' => array(
                        array(
                                'taxonomy' => $value,
                                'field' => 'slug',
                                'terms' => $termsarray,
                        )
                )
        );  
        $newquery = new WP_Query( $myargs );    
        //echo "newquery is <pre>";print_r($newquery);echo "</pre>";  //DEBUG

        // now we have all the posts for the custom taxonomy
        // so we can print whatever we like

        // Page Header
        echo '<h1 class="page-title">'.$value.'</h1>';

        while ( $newquery->have_posts() ) {
            $newquery->the_post();
            the_title( '<h1 class="entry-title">', '</h1>' );

        }

    }

        //echo "<br/>TESTING - END<br/>";  //DEBUG  
}

This is an extract from taxonomy.php. The function “checktax” does the work.

get_header(); ?>

<div class="wrap">

    <?php if ( have_posts() ) : ?>
        <header class="page-header"><!-- taxonomy -->
            <?php
                checktax();     

                the_archive_title( '<h1 class="page-title">', '</h1>' );
                the_archive_description( '<div class="taxonomy-description">', '</div>' );
            ?>
        </header><!-- .page-header -->
    <?php endif; ?>

Lastly, this is a screen snapshot.
enter image description here