array of objects to do_action, callback gets singular object?

So I was passing an array of objects through an action today, no biggy, and things were working fine. Until I was iterating over one of the arguments to a callback and started getting errors. The only difference was that the passed array to the do_action call only had a single object in it.

Confused by this, I simply didn’t call the action unless the array had a count of over 1 (the action is caching something FYI).

Looking into the function definition I found this on line 411 of wp-includes/plugin.php

if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)

which is what was causing my array of a single object to become just an object. To me this is really weird, if I pass an array to an action then I expect an array on other side. I’m using WordPress 3.7.1 and am wondering if anyone knows why do_action has this behavior? A ticket or a link to something in the wordpress repository would work as an answer for me.

EDIT: Request for code and actions:

I create an action within my code like so:

add_action('hs_cache_merchants', array('HoneyCache', 'cacheMerchants'), 10, 1);

It is called like so within a method that retrieves data from the database, where $merchants is an array of objects.:

do_action('hs_cache_merchants', $merchants);

And then my callback registered with the add_Action:

public static function cacheMerchants($merchants){
    if(!is_array($merchants)){ /* WordPress will convert an array of a single object to just the object. */
        $merchants = array($merchants);
    }

    set_transient(HoneyMerchant::CACHE_CURRENT_MERCHANTS_KEY, $merchants, HoneyMerchant::CACHE_CURRENT_TIME);
}

If I modify my prototype to be

public static function cacheMerchants(Array $merchants){

then I will get the error:

 PHP Catchable fatal error:  Argument 1 passed to HoneyCache::cacheMerchants() must be an array, object given

I used print_r in the function that calls do_action and noted an array with a single object in it, this only happens if the array has 1 item in it, since that’s part of what that if in the core checks.

1 Answer
1

I don’t know if you solved this, I just had same problem,

Second argument in do_action has special check if it is array with only one object,
In that case they use reference to object in array instead of array with object. I believe they use this method to pass and preserve reference through function with variable arguments.

I used do_action_ref_array() to avoid this.

Leave a Comment