If you are displaying a post, how do you find and show the posts category or categories like this ?
Parent Category > Child Category > The current post

Unfortunately the WordPress database is not structured to store Posts with their corresponding category/taxonomy parent ID on the same column. Had it been so, one could easily call the parent category based on the data present in the posts table.

Its for the many small nuisances like this where custom developed content management systems triumph, but anyhow, WordPress is WordPress is WordPress so we put on our thinking caps, study the core, google for all its worth and make do with what we have.

The solution by thewebtaylor.com is promising but as I explain below, with multiple parents assigned to a post, its hit and miss in all cases. The link provided, while being workable solution, will select the first index of the array as the parent even though it may be incorrect. Logically speaking, and considering a few other aspects with one being feasibility, this seems to be the only way around unless of-course someone makes it really worth your while.

Continuing…

To find the parent categories of a post, you could use the function

get_the_terms()

by passing 2 parameters, the post ID and the Post type:

get_the_terms($my_post_id, 'my-custom-post-type');

This, function returns an object of all the rows from the database table

wp_term_relationships

where the object_id matches the posts ID.

This doesn’t return the categories in order of hierarchy but its a start.

Once we have this group of terms, we can loop through the array and find the term where the parent is 0. This solves the problem of locating all the categories but it also adds another complication:

WordPress posts can be assigned to multiple categories, So;

Lets say we have a post called “My fish”
“My fish” can be assigned to the category of “Ponds” AND “Pets”.

Once we display the Post “My-fish”, we dont know if the user came from the category “Ponds” or “Pets”, so even though we have all the categories of “My-fish”, which category do we choose to display as the parent without knowing the users previous preference?

Okay, so now we need to choose between the array of categories… Which category wins and how do we decide ?

We could get the REFERRING URL with

wp_get_referer();

or

$_SERVER

which both return the same data, we can then compare the HTTP_REFERER with the slug of the terms returned, if we have a match then that would be the correct category to display.

Problem solved? Nope… its gets weirder!

Lets clarify our progress quickly:

  • We know the page
  • We have all the terms associated to the post using get_the_terms()
  • We used the referring URL to determine which term to display as the parent using the $_SERVER[‘HTTP_REFERER’], cleaning the URL and comparing it with the slug of each term.

So now whats the problem now?

The problem now is that our winning terms, the one we’ve selected to show can also have more than one parent, and this is where we take off our thinking caps and get the job done with:

//returns the parent categories of a post (parents without children)
function get_grandparents($post_id, $post_type)
{
   $the_parent_category = '';
   $associated_categories =  get_the_terms($post_id, $post_type);
   foreach($associated_categories as $cat)
   { 
      if($cat->parent == '0')
      { 
         $the_parent_category = $cat;
      }
   }
   
   return $the_parent_category;
}

//returns the direct categories of a post (these terms have parent categories)
function get_parents($post_id, $post_type)
{
   $the_parent_category = '';
   $associated_categories =  get_the_terms($post_id, $post_type);
   foreach($associated_categories as $cat)
   { 
      if($cat->parent != '0')
      { 
         $the_parent_category = $cat;
      }
   }
   
   return $the_parent_category;
}

These 2 function can be incorporated into a single function like like:

function get_parents($post_id, $post_type, $level)
{
   $the_parent_category = '';
   $associated_categories =  get_the_terms($post_id, $post_type);
   foreach($associated_categories as $cat)
   { 
      if($level == 'parent')
      {
         if($cat->parent == '0')
         { 
            $the_parent_category = $cat;
         }
      }
      elseif($level == 'grandparent')
      {
         if($cat->parent != '0')
         { 
            $the_parent_category = $cat;
         }
      }
   }
   
   return $the_parent_category;
}

If anyone does actually read this post looking for a solution, these are my recommendations:

  1. Use a plugin
  2. If you are against the use of unnecessary plugins as I am then dont nest your breadcrumb too deep. Show 1 category and then take the home, so …. HOME (OR POST TYPE) – CATEGORY – THE POST, If you need to nest deeper than this then you probably need to reconsider your websites structure. Pages nested too deep will suffer with SEO.

Need a website, consultation or customisation? Let’s speak