j.kaspar
j.kaspar

Reputation: 761

Wordpress - custom template page for a parent category and all child categories

In WP 5.4.2 I want to create a custom archive page for a category and all it's child categories. I am aware of the template file hierarchy:

1. category-slug.php
2. category-ID.php
3. category.php
4. archive.php
5. index.php

but if I understand correctly and if I did all the testing right, the category-slug.php, or the category-id.php scheme applies to a single category regardless of the category hierarchy.

Let's say I have following categories:

colors (id 2)
- red  (id 10)
- green (id 11)
- blue  (id 12)

I need a single template file for all of them. Simply creating category-colors.php or category-2.php doesn't work. It applies to the single category (colors) only. I want it to apply to all the current child categories, as well as all the child categories I add in the future. Is it possible? If so, please advice how.

Upvotes: 3

Views: 2416

Answers (1)

FluffyKitten
FluffyKitten

Reputation: 14312

There are a couple of ways to do this, but using the category_template filter to let you use a custom category template seems the most common.

The function below will let you dynamically check back through the parent levels of the current category until it finds a template called "category-[parent slug]" for the closest ancestor category or it reaches the top level - whichever is first.

Suppose you have something like:

 - products
    - hardware
    - food
      - dairy
      - vegetables
  1. On the dairy page, it will first check if you have a slug called category-dairy.php.
  2. If you do, it will return it.
  3. If you don't, it will look for category-food.php.
  4. If that's not found, it will look for category-products.php.

Add this to your functions.php - this is untested by the code is well commented so you can understand how it works:

function get_template_for_category( $template ) {

    if ( basename( $template ) === 'category.php' ) { // No custom template for this specific term, let's find it's parent
        // get the current term, e.g. red
        $term = get_queried_object();

        // check for template file for the page category
        $slug_template = locate_template( "category-{$term->slug}.php" );
        if ( $slug_template ) return $slug_template;

        // if the page category doesn't have a template, then start checking back through the parent levels to find a template for a parent slug
        $term_to_check = $term;
        while ( $term_to_check ->parent ) {
            // get the parent of the this level's parent
            $term_to_check = get_category( $term_to_check->parent );

            if ( ! $term_to_check || is_wp_error( $term_to_check ) )
                break; // No valid parent found

            // Use locate_template to check if a template exists for this categories slug
            $slug_template = locate_template( "category-{$term_to_check->slug}.php" );
            // if we find a template then return it. Otherwise the loop will check for this level's parent
            if ( $slug_template ) return $slug_template;
        }
    }

    return $template;
}
add_filter( 'category_template', 'get_template_for_category' );

References:

Upvotes: 4

Related Questions