[wp-hackers] PHP4->5 upgrade heads up

Brian Layman Brian at TheCodeCave.com
Thu Jul 13 21:55:54 GMT 2006


On a related topic, I've been meaning to mention the widgets problem I'd
discussed with Andy Skelton.  In the end it was related to the change in
array_merge between PHP4 and PHP5 and could occur in anyone's code.  So, if
someone missed this array_merge change, I thought a public post might be
beneficial...  

PHP5's array_merge now blows up on non-array variables.  It seems some PHP
array functions, specifically array_slice, return non-array (unset)
variables.  So, in short, an array_merge that works in php4 may not work in
php5 unless you follow the same convention Mark Jaquith recommended when he
said "cast to array before foreach".  

If a variable's content hasn't already been verified as containing an array,
you should cast to array before using it in an array_merge.  
That could look like this:
  $result = array_merge(array('a'=>1,'b'=>2), (array) $second);

Details on the change can of course be seen here:
http://us2.php.net/array_merge

I'm sure this is old news for some. So, unless you want details of what we
changed, you probably won't care to read on.

---- 

For a practical example, we could look at the now fixed issue from
widgets.php.

An array slice was done in a fashion similar to this:
  $registered_widgets[$name]['params'] => array_slice(func_get_args(), 2)

We are assuming that the problem arose when the 2 argument was defaulted to
''.

The line that actually blew up was this one:
 $params = array_merge(array($sidebar),
$registered_widgets[$name]['params']);

The error was:
"Warning: array_merge() [function.array-merge]: Argument #2 is not an array
in ./wp-content/plugins/widgets/widgets.php on line 154"

There is nothing that indicates array_slice changed between 4 and 5.  So, it
appears the only difference was in array_merge.  Wrapping the error line in
an "if (is_array($registered_widgets[$name]['params']))" solved the problem,
but it was not the fix we used.

I remembered Mark's coding style suggestion for foreach in
(http://comox.textdrive.com/pipermail/wp-hackers/2006-July/006930.html) and
applying it solved the problem in a simpler fashion.  Andy checked in this
new line:
  $params = array_merge(array($sidebar), (array)
$registered_widgets[$name]['params']);

FYI, we'd tried this first:
  $registered_widgets[$name]['params'] => (array)
array_slice(func_get_args(), 2)
but it had no affect.

-

I looked at every instance of array_merge in the 2.03 code, and it seems
that all of them are in places where the parameters are guaranteed to have
either a value or array() specified.  So, this is mostly a heads up to
plugin authors.  I haven't done any examination of the plugin code base.



More information about the wp-hackers mailing list