php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #19699 'array_walk()' violates recommended 'allow_call_time_pass_reference=Off'
Submitted: 2002-10-01 17:38 UTC Modified: 2004-07-27 14:23 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: fvu at wanadoo dot nl Assigned:
Status: Not a bug Package: Documentation problem
PHP Version: 4.2.3,4.3.0-dev OS: Windows
Private report: No CVE-ID: None
 [2002-10-01 17:38 UTC] fvu at wanadoo dot nl
The PHP manual contains the following note about 'array_walk()':

   Note: 
   If func needs to be working with the actual values of the array, specify 
	that the first parameter of func should be passed by reference. Then any 
	changes made to those elements will be made in the array itself. 

So if you want to let 'array_walk()' pass the third parameter by reference, 
you're inclined to specify that the third parameter of func should be passed by 
reference.  In the example underneath, the notation '&$userData' is used to 
specify so:

   function PrepareBowl($value, $key, &$userData) {
     print 'Mixed so far... ' . ($userData .= "$value ") . "<br>\n";
   }
 
   $ingredients = array('peach', 'cherry', 'alchohol');
   $bowl = '';
   array_walk($ingredients, 'PrepareBowl', $bowl);
   print "Bowl: $bowl";

This doesn't work however; '$assembly' will not be passed by reference and the 
output will be an empty 'bowl':

   Mixed so far... peach 
   Mixed so far... peach cherry 
   Mixed so far... peach cherry alchohol 
   Bowl: 

Only when you use the '&' notation within 'array_walk()' to specify that the 
third parameter should be passed by reference:

   array_walk($ingredients, 'PrepareBowl', &$bowl);

the output will be as expected:

   Mixed so far... peach 
   Mixed so far... peach cherry 
   Mixed so far... peach cherry alchohol 
   Bowl: peach cherry alchohol 

but, using the recommended php.ini setting 'allow_call_time_pass_reference=Off',
you'll receive the warning:

   Warning: Call-time pass-by-reference has been deprecated - argument
	passed by value; If you would like to pass it by reference, modify the 
	declaration of array_walk(). If you would like to enable call-time 
	pass-by-reference, you can set allow_call_time_pass_reference to true in 
	your INI file. However, future versions may not support this any longer.

This looks the same like bug 4116 (http://bugs.php.net/bug.php?id=4116), posted Apr 12, 2000.  Although this bug is closed with a reply that it works like the 
replier think it should work, this doesn't seem logic to me because the first 
parameter *is* passed by reference without specifying; try:

   array_walk(array('peach', 'cherry', 'alchohol'), 'PrepareBowl', &$bowl);

and you'll receive:

   Fatal error: Only variables can be passed by reference ...

Furthermore, I can't see much use of passing a third variable to 'array_walk()'
by value, modify it by passing it to func by reference ... without receiving 
back the modified variable.

Would it be a suggestion to let 'array_walk()' receive the third parameter by 
reference if specified so in the receiving func?  This would be in line with
the behaviour of the first parameter to func.


Freddy Vulto

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-10-03 16:27 UTC] jmoore@php.net
OK.

Manual is incorrect here, in PHP4 functions either specify if an arg is passed by ref or by value. In array_walk only the first argument is ever passed by reference. I can see that passing userdata by reference would be nice but unfortuantly it is too much of a big change that could break too many scripts to make as this point as people may be relying on the fact it is passed by reference.

For example

function my_function($value, $key, $userdata)
{
     $userdata = strrev($userdata.$key.$value);
}

$array1 = array("one", "two", "three")l
$mydata = "array1";
array_walk($array1, 'my_function', $mydata);

This POOR example would not work with thrid parameter passed by ref so for now am changing this to a documentation problem as the documentation is currently slightly misleading in it advocates using calltime pass by reference when infact the first param only is ever passed by reference.

- James
 [2002-10-04 03:04 UTC] fvu at wanadoo dot nl
James,

indeed your example would break existing code if '$userdata' would *always* be passed by reference.

I think the solution would be to let array_walk pass '$userdata' by reference only if specified so in 'my_function' (just the same as the first parameter behaves).

Your example would still work then since '$userdata' in my_function() is specified without an ampersand, so it should be passed by value.
 [2002-11-26 19:25 UTC] tater at potatoe dot com
Why not just add a flag parameter to array_walk() saying that the userdata param should be a reference?

If "future versions may not support this any longer", there will be no way for array_walk to modify external variables, and that's a serious BC problem.
 [2003-07-15 07:09 UTC] glen at delfi dot ee
well, i agree with fwu, that
1. using ampersand = passing by reference
2. using without = passing a copy

maybe James should look at this example, understanding the differences:

http://hellsgate.online.ee/~glen/array_walk.php

and, besides, there's no way to silence pass_by_reference warning. tried
    @array_walk($a, array(&$this, 'count'), &$c);
and
    array_walk($a, array(&$this, 'count'), @&$c);

also tested on 5.0.0b1
 [2003-07-15 07:19 UTC] glen at delfi dot ee
btw, there's workaround for the issue.
create container array, and work on it

$container = array(&$thing);
array_walk($a, array(&$this, 'count'), $container);

and in 'count' function play on first element of $userData array

see:
http://hellsgate.online.ee/~glen/array_walk2.php
 [2004-07-27 14:23 UTC] vrana@php.net
It's not possible to pass third parameter by reference with allow_call_time_pass_reference and it's not stated in the documentation. Thus there is no documentation error.

I only noticed that first parameter is passed by reference.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 19:01:29 2024 UTC