Make WordPress Core

Opened 5 years ago

Closed 19 months ago

#37728 closed defect (bug) (fixed)

hide_empty doesn't work correctly in get_terms when no taxonomy specified

Reported by: smerriman Owned by: boonebgorges
Milestone: 5.3 Priority: normal
Severity: normal Version: 4.5
Component: Taxonomy Keywords: has-patch needs-unit-tests reporter-feedback needs-testing
Focuses: Cc:


In #35495, the taxonomy argument to get_terms was made optional. Calling get_terms without specifying a taxonomy will return terms from all taxonomies.

However, if taxonomy isn't provided, hide_empty (when true, as per default) does not work correctly. Parent terms which are empty themselves but have nonempty child terms are not returned.

You can replicate this by creating an empty category with non-empty child categories. Using:

get_terms() - won't include the category
get_terms(array('taxonomy'=>'category')) - will include the category
get_terms(array('taxonomy'=>array('category','post_tag'))) - will include the category

This is caused by the get_terms function in WP_Term_Query. $has_hierarchical_tax gets set to true if a single hierarchical taxonomy is passed, or multiple taxonomies with at least one hierarchical. However, if no taxonomies are passed, this never gets set to true.

In this case it should be set to true, since it will at minimum include the in-built category taxonomy.

Attachments (1)

37728.patch (386 bytes) - added by smerriman 5 years ago.
set has_hierarchical_tax to true when querying all taxonomies

Download all attachments as: .zip

Change History (7)

5 years ago

set has_hierarchical_tax to true when querying all taxonomies

#1 @swissspidy
5 years ago

  • Keywords has-patch needs-testing needs-unit-tests added

#2 @desrosj
22 months ago

  • Keywords reporter-feedback close added

Hi @smerriman,

Thanks for this ticket! My apologies that it took so long to receive a response.

I am unable to reproduce the issue you have described in the latest version of WordPress (5.1.1). Are you still able to recreate this? If so, can you provide some more detailed steps, or some unit tests that prove get_terms() is not working as expected?

Marking as a close candidate pending reporter-feedback since this worksforme.

#3 @smerriman
22 months ago

I'm getting exactly the same results now as 3 years ago by following the steps mentioned in my original post:

  • install a new version of WP
  • create a category, and a subcategory
  • create a post, and place it inside the subcategory only

Calling get_terms() will return the subcategory, but not the parent category.
Calling get_terms(array('taxonomy'=>'category')) and get_terms(array('taxonomy'=>array('category','post_tag'))) both include the parent category.

The original one line fix still is a valid solution.

Last edited 22 months ago by smerriman (previous) (diff)

#4 @smerriman
19 months ago

  • Keywords close removed

Have just run into this bug on another site I'm working on. I wanted to list all subcategories of a parent category, so used:

$terms = get_terms(array('child_of'=>1));

but was returned an empty array, because posts only exist in the subcategories, and none directly in the parent category.

In this case, I could add the taxonomy parameter to fix it:

$terms = get_terms(array('child_of'=>1,'taxonomy'=>'category'))

But it would be nice if this bug can be resolved, given I reported it, along with a trivial one line fix, 3 years ago.

#5 @boonebgorges
19 months ago

  • Milestone changed from Awaiting Review to 5.3

I've reproduced the inconsistency by writing a couple of tests.

IMO it's somewhat odd semantically that 'hide_empty' would return empty parents with non-empty children. But this is the historical behavior of hide_empty, so it should be matched when $taxonomies is empty. So the fix looks correct.

#6 @boonebgorges
19 months ago

  • Owner set to boonebgorges
  • Resolution set to fixed
  • Status changed from new to closed

In 45888:

Taxonomy: Ensure consistency of hide_empty in term queries when taxonomy is excluded.

When querying for terms in hierarchical categories using hide_empty=true,
results have historically included parent terms which are themselves
unattached to any objects (are "empty") but which have non-empty descendent
terms. Because this process involves walking the descendant tree, we avoid it
when we detect that the queried taxonomies are not hierarchical. (This
behavior was introduced in [5525].)

When the taxonomy parameter of get_terms() was made optional - see #35495,
[36614] - it affected the mechanism for avoiding unneccessary tree walks,
since there may not be any explicitly declared taxonomies to run through
is_taxonomy_hierarchical(). As a result, term queries excluding taxonomy
did not check descendants, and empty parents with non-empty children were not
included in hide_empty results.

We correct the behavior by crawling term descendants when the taxonomy
argument is absent, which means that we're querying for terms in all taxonomies.

Props smerriman.
Fixes #37728.

Note: See TracTickets for help on using tickets.