I've got myself into a little pickle, and while I'm so close, my understanding of PHP is letting me down.

I want to display the image associated with each category in the menu - working from the answer over here I needed to make that code work with a custom taxonomy as I'm working with woocommerce product categories. I should add that my use case is fairly narrow, so I stripped much of the original answer away to focus on this product category image.

First I add all this to the menu.

<?php add_filter('wp_nav_menu_args', 'add_filter_to_menus');
function add_filter_to_menus($args) {
    add_filter( 'wp_setup_nav_menu_item', 'filter_menu_items' );
    return $args;
} ?>

The next bit is the problematic stuff...

function filter_menu_items($item) {
    // if the menu item is taxonomy
    if( $item->type == 'taxonomy') {

        // explicitly set the category for now
        $cat_base = 'product-category';

        // strip away everything except the term path
        $cat_path = str_replace(home_url().'/'.$cat_base.'/', '', $item->url);

        // get the term object by using the slug
        $term = get_term_by('slug', $cat_path, 'product_cat');

        // get the term id from the object
        $term_id = $term->term_id;

        // $term_array = get_object_vars($term);
        // echo '<pre>'; var_dump( $term ); echo '</pre>';

        $thumbnail_id = get_woocommerce_term_meta( $term_id, 'thumbnail_id', false );
        $image = wp_get_attachment_url( $thumbnail_id );
        if( !empty($image) ) {
            $item->title =  $item->title . '<span class="menu-image"><img src="' . $image . '" alt=""></span>';
} ?>

Im having a problem getting the $term_id from the $term object. I get a notice Trying to get property of non-object. But when I do a var_dump on $term i get the following:

<pre>object(stdClass)#4511 (10) {
  string(9) "Furniture"
  string(9) "furniture"
  string(11) "product_cat"
  string(0) ""
  string(3) "raw"

This looks to me like $term is an object, so why the non-object notice and a total failure? You can also see commented out that I tried to turn this object into an array, but that didn't work out so well either...

Apologies for my PHP skills here - I'm clearly not understanding something fairly basic, but I really did want to solve this myself, but I must admit defeat!

Many thanks for reading.


As alluded to in Mark's answer below, the default get_term_by() returns an object. Quite why my code was getting caught up on the is-it-or-isnt-it-an-object thing, I don't know. Using $term = get_term_by('slug', $cat_path, 'product_cat', ARRAY_A); did the trick though, along with using array rather than object syntax to select the value I wanted.

As an aside, I realised that the above would return false if these product categories were nested, as there would be two (or more) slugs being returned; so I did a bit more cleaning up of the slug before attempting to get the term id from it.


$cat_path = str_replace(home_url().'/'.$cat_base.'/', '', $item->url);


$path = parse_url($item->url, PHP_URL_PATH);
$path_trimmed = trim($path, '/');
$parts = explode('/', $path_trimmed);
$cat_path = end($parts);

2 Answers 2


Not sure why your object is returning the non-object notice, but you can set the output of get_term_by to OBJECT, ARRAY_A, or ARRAY_N - You'll want to use ARRAY_A and then access the term ID via $term['term_id'].

  • 1
    Thanks Mark! Can't vote up yet, but this got me on the right track. I changed a few other things which I'll edit into the above question for clarity, but get_term_by ARRAY_A did the trick.
    – PUncle
    Aug 6, 2015 at 11:51

I think this will work for you:

function wpa_category_nav_class( $classes, $item ){
    if( 'product_cat' == $item->object ){
        $classes[] = 'menu-category-' . $item->object_id;
    return $classes;
add_filter( 'nav_menu_css_class', 'wpa_category_nav_class', 10, 2 );
  • 2
    Welcome to the site. Please take a minute to explain your answer instead of just leaving code.
    – user9447
    Aug 5, 2016 at 14:41

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.