1

I have 3 headers (header.php, header2.php, and header3.php). I want to always display header.php at the top. Below header.php, I want a second header to display depending on what category the post is. If the post is Grizzly Bears, I want header2. If the post is Peace Pipes, I want header3.

I understand displaying 2 headers with:

<?php
get_header(); 
get_header(header2); 
?>

But how can I make the second header dependent on if a category is tagged (or tag is added, to make this question complete)?

EDIT: Due to the help of jgraup and karpstrucking, I see this question is not complete:

Using ...

if ( has_category( 'Grizzly Bears' ) ) {
  get_header( 'header2' );
} else if ( has_category( 'Peace Pipes' ) ) {
  get_header( 'header3' );
}

... works only if the has_category is the child-most category. I would like to apply the condition to the parent-most category. This code fails for this. For example, I check parent category 'Grizzly Bears' and child category 'Grizzly Bears Fishing' and I can't use the code for 'Grizzly Bears'.

Thanks, JM

3 Answers 3

1

You can use the has_category() function for this:

if ( has_category( 'Grizzly Bears' ) ) {
  get_header( 'header2' );
} else if ( has_category( 'Peace Pipes' ) ) {
  get_header( 'header3' );
}

You can add the has_tag function as well. Both accept an array of term IDs, names or slugs if you want to check multiples at once.

Edit: changed in_category to has_category for consistency and potential future deprecation

1
  • Thank you. I updated my question due to finding something more Dec 21, 2015 at 22:07
1

EDIT from COMMENTS

All I want to do, in this case, is display a header(header)2 -IF-a post has a certain category checked. I might have "Grizzly bears" only, or might have both "Grizzly bears" and its child "Grizzly bears fishing," or I might have another child "Grizzly bears eating" but as long as that "Grizzly bears" category is checked, I want the -THEN- statement to happen.

We can still use the same function that we have created in the ORIGINAL ANSWER, but we will aplly it a bit different. We will need to get the categories the post belongs to and then check if Grizzly bears are among them

$parent_cat  = 1, //Pass the ID, this will ID for 'Grizzly bears'    
$descendants = get_term_descendants( $parent_cat );
$post_terms  = get_the_category( get_the_ID() );
$ids         = wp_list_pluck( $post_terms, 'term_id' );
if ( $decendants && !in_array( $parent_cat, $ids ) ) {
    if ( has_category( $decendants ) ) {
        // Post belongs to parent cat descendants but not parent cat
    }
} elseif ( in_array( $parent_cat, $ids ) ) {
    // Post belongs to the parent category
} else {
    // Post does not belong to parent cat or any of its decendants
}

ORIGINAL ANSWER

Your question is a bit hard to understand, but I will answer to how I read it.

If you need to apply a certain header to each to the top level term and all of its descendants, you can write your function using get_terms() to return all descendants from the given top level parent

FEW NOTES BEFORE CODE:

  • The code is untested and might be buggy. Be sure to test this locally first with debug turned on

  • The code requires at least PHP 5.4

  • It can be quite verbose as we need to do a lot of work to get all the descendants from a top level term. Note, I have explained this, but for performance, make sure that you pass the ID rather than slug to the function, and do not use names

CODE

function get_term_descendants( $term = '', $taxonomy = 'category' )
{
    // First make sure we have a term set, if not, return false
    if ( !$term )
        return false;

    // Validate and sanitize taxonomy
    if ( 'category' !== $taxonomy ) {
        $taxonomy = filter_var( $taxonomy, FILTER_SANITIZE_STRING );
        // Make sure the taxonomy is valid
        if ( !taxonomy_exists( $taxonomy ) )
            return false;
        // Make sure our taxonomy is hierarchical
        if ( !is_taxonomy_hierarchical( $taxonomy ) )
            return false;
    }

    // OK, we have a term and the taxonomy is valid, now we need to validate and sanitize the term
    if ( is_numeric( $term ) ) {
        $term = filter_var( $term, FILTER_VAILDATE_INT );
    } else {
        $term_filtered = filter_var( $term, FILTER_SANITIZE_STRING );
        $term_object   = get_term_by( 'slug', $term_filtered, $taxonomy );
        $term          = filter_var( $term_object->term_id, FILTER_VAILDATE_INT );
    }

    // Everything is sanitized and validated, lets get the term descendants ids
    $term_descendants = get_terms( $taxonomy, ['child_of' => $term, 'fields' => 'ids'] );

    // Check if we have terms
    if ( !$term_descendants )
        return false;

    // We have made it, return the descendants
    return $descendants;
}

Our function get_term_descendants() will now either hold an array of descendant term ID's of the term passed to the function or will return false if the passed term dont have descendants

We can now use our function and pass the returned array of ids directly to has_category()

NOTE: You can either pass the parent term ID or slug to the function. Do not use names as hierarchical terms can have duplicate names accross different hierarchies. Also note, passing the slug to the function is a bit more expensive because we will use get_term_by() to get the term ID from the slug. For performance, try to always pass the ID

$parent_cat = 1, //Pass the ID, can pass the slug, but reread the note above
$descendants = get_term_descendants( $parent_cat );
if ( $decendants ) {
    $term_array = array_merge( $parent_cat, $descendants );
} else {
    $term_array = $parent_cat;
}
// Now we can check if the post belongs to the parent cat or one of his descendants
if ( has_category( $term_array, $post ) ) {
    // Post belongs to parent cat or one of his descendants
} else {
    // Post does not belong to the parent or any of his descendants
}
4
  • Hi Pieter, I'm still going to look at your code further. It will take me some time. All I want to do, in this case, is display a header(header)2 -IF-a post has a certain category checked. I might have "Grizzly bears" only, or might have both "Grizzly bears" and its child "Grizzly bears fishing," or I might have another child "Grizzly bears eating" but as long as that "Grizzly bears" category is checked, I want the -THEN- statement to happen. Dec 22, 2015 at 6:36
  • OK, I seem to understand now, will update the answer Dec 22, 2015 at 6:43
  • Actually, I've used the theme a different way (as a new theme, and not as a theme "test-drive", and now the first code seems like it might work. I'm going to check this before I trouble you or anyone else further on this matter. I think it might work already. Dec 22, 2015 at 6:55
  • I have update the answer and some code. Feel free to check it out Dec 22, 2015 at 7:13
0

For all categories (wp_get_post_categories)

The function wp_get_post_categories() retrieve a list of categories for a post.

get_header('header');

Conditional based on has_category

Check if the current post has any of the given categories. The given categories are checked against the post's categories' term_ids, names and slugs. Categories given as integers will only be checked against the post's categories' term_ids.

if(has_category('bears', $post)) {
    get_header('header2');
}
else if(has_category('pipes', $post)) {
    get_header('header3');
}
7
  • Thank you. I updated my question due to finding something more Dec 21, 2015 at 22:07
  • Can you just check against the contents of wp_get_post_categories - codex.wordpress.org/Function_Reference/wp_get_post_categories
    – jgraup
    Dec 21, 2015 at 22:24
  • Just a note, wp_get_post_categories() is quite expensive to run as the results aren't cached. Running wp_get_post_categories() 100 times makes 100 db calls. Use get_the_categories() which are cached. If the post categories is already added in the cache, you can run the code 100 times without making even 1 db call Dec 22, 2015 at 5:28
  • @PieterGoosen, you should consider adding to User Contributed Notes at the bottom of developer.wordpress.org/reference/functions/… and/or simply updating the codex.
    – jgraup
    Dec 22, 2015 at 5:43
  • Will do so if I time again. The codex is really such a mess and so many pages are nothing more that a pile of crap. The issue will always be that anyone with a valid wordpress.org account can update the codex, so a total newby tries something (totally incorrect) and it works and he updates the codex with what worked for him. The next guy comes, also a newby, he accepts that what is in the codex is true and he uses that incorrct info thinking it is the way to go because after all, the codex in updates by core developers, WRONG. The info he got was from a newby which also knows nothing ;-) Dec 22, 2015 at 5:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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