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
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.