Make WordPress Core

Opened 16 months ago

Last modified 8 weeks ago

#26234 new defect (bug)

Passing array of taxonomies to the_terms() triggers "array to string" conversion warning

Reported by: johnjamesjacoby Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 2.2
Component: Taxonomy Keywords: needs-unit-tests needs-patch
Focuses: Cc:


To duplicate in a loop, call:

the_terms( get_the_ID(), array( 'category', 'post_tag' ) );

I expected to output the terms for a post across multiple taxonomies. Instead, an array to string conversion warning is returned.

I've narrowed this down to an inconsistency in the way caching is handled between update_object_term_cache() and get_object_term_cache(), namely that update handles multiple taxonomies and relationships, and get assumes only one taxonomy is passed.

The call stack to the error looks something like:

  • the_terms()
  • get_the_term_list()
  • get_the_terms()
  • get_object_term_cache()

Each of the functions in the above stack safely handles multiple taxonomies, except for get_object_term_cache(). If get_object_term_cache() were fixed, wp_get_object_terms() would fire (which also safely handles multiple taxonomies) and the_terms() would work as I expected.

Attachments (2)

26234.patch (3.4 KB) - added by johnjamesjacoby 16 months ago.
I can get you a toe by 3 o'clock this afternoon, with nail polish
26234.2.patch (3.6 KB) - added by johnjamesjacoby 16 months ago.
Same as 26234.patch but also brings clean_object_term_cache() into the mix

Download all attachments as: .zip

Change History (6)

comment:1 @johnjamesjacoby16 months ago

One possible, albeit hacky, solution, is to concatenate the taxonomies into a cache key, and pass that around instead.

Poking around in update_object_term_cache()will likely result in losing at least one finger (and probably a pinky toe) and although I'm justifiably afraid to go digging, my incoming patch does so with reckless abandon.

I'm also fully aware of the 5 year taxonomy plan, and prematurely agree that complicating things further for everyone is likely not worth the expense later. If nothing else, consider this a ticket for posterity until then.

(Edit: grammar all the words)

Last edited 16 months ago by johnjamesjacoby (previous) (diff)

@johnjamesjacoby16 months ago

I can get you a toe by 3 o'clock this afternoon, with nail polish

@johnjamesjacoby16 months ago

Same as 26234.patch but also brings clean_object_term_cache() into the mix

comment:2 @stewarty14 months ago

Interestingly this affects me on PHP 5.4 but not on 5.3.x.

Something must've changed in the internals. I'm not sure what though, pretty much a noob with digging through PHP version changes

Would intentionally changing my array to a string before passing to this function help?


comment:3 @wonderboymusic11 months ago

  • Keywords has-patch needs-unit-tests added; 2nd-opinion removed
  • Milestone changed from Awaiting Review to Future Release

Should be done in tandem with #27764 - if someone picks these up and works on them, can be 4.0

comment:4 @boonebgorges8 weeks ago

  • Keywords needs-patch added; has-patch removed

The kind of cache concatenation suggested by [26234.2.patch] is not very beautiful, and will result in significant cache pollution, since you might end up with 'post_tag' relationships cached in many different places.

I suggest the following tack: Keep the {$taxonomy}_relationships caches independent of one another. In get_the_terms(), do something like this:

$terms = array();
foreach ( (array) $taxonomy as $_taxonomy ) {
    $_terms = get_object_term_cache( $post->ID, $_taxonomy );

    if ( false === $_terms ) {
        $_terms = wp_get_object_terms( $post->ID, $_taxonomy );
        wp_cache_add( $post->ID, $terms, $_taxonomy . '_relationships' );

    $terms = array_merge( $terms, $_terms );

Then do some logic to sort $terms by 'name' (since that's the only sort order supported by get_the_terms().

Note: See TracTickets for help on using tickets.