Am 28.09.2012 00:07, schrieb Christoph Becker:
> M. Strobel wrote:
>> Yes, but I had a problem with callback functions: if you created them with
>> create_function this was a call-time call-by-reference.
>
> Could you please give an example. For example
>
> array_walk($array, create_function('&$x', '$x = trim($x);'));
>
> works fine.
My requirement was not to change the array, but to return data from inside the callback.
In older PHP you could ignore the warning about Call-time pass-by-reference and give
the callback function a third parameter by ref.
Now there is only one way to do it, see the command line test code below.
/Str.
<?php
/**
* Testen von array_walk mit Closure und use-Parameter by reference
*/
error_reporting(-1);
$sub1 = array('I'=>'Igor', 'J'=>'Jan', 'K'=>'Karl', 'L'=>'Liugi', 'M'=>'Michael');
$sub2 = array('A'=>'Alexa', 'B'=>'Brunhilda','C'=>'Carla','D'=>'Dina','E'=>'Elsa');
$a['F'] = 'Frantzi';
$a['G'] = 'Gustavo';
$a['Gentlemen'] = $sub1;
$a['H'] = 'Hillbilly';
$a['Ladies'] = $sub2;
echo "Number of elements using count(): ", count($a), PHP_EOL;
echo (array_key_exists('K', $a)) ? 'array_key_exists() does work in
sub-arrays':'array_key_exists() does NOT work in sub-arrays', PHP_EOL;
echo '------------------------------', PHP_EOL;
echo "\tStart run\n";
echo '------------------------------', PHP_EOL;
/**
* try a call by ref in a closure use list
*
* This is the best solution to return values from the callback.
*/
$f0 = function ($v,$k,$l) use(&$var) {
if ($k==$l) $var = $v;
};
$var = 'something';
echo "var before array_walk: ($var)\n";
# this does work, var will be defined: unset($var);
$rc = array_walk_recursive($a, $f0, 'M');
echo "rc = $rc, var after array_walk f0 with call by ref in use list: ($var)\n";
echo '------------------------------', PHP_EOL;
/**
* testing f0 in a different scope
*/
function func0($arr,$callback) {
$var = 'Testing in a local scope with f0';
echo "var before array_walk: ($var)\n";
$rc = array_walk_recursive($arr, $callback, 'M');
return ($rc) ? 'Call successful, var is '.$var : 'Call NOT successful, var is
'.$var ;
}
echo func0($a,$f0), PHP_EOL;
echo "Variable in global scope after call: $var\n";
echo "Result: the var by ref in the use list binds to the global scope where it was
defined.\n";
/**
* trying to put a call by ref into the parameter list
*/
$f1 = function ($v,$k,$l, &$var) {
if ($k==$l) $var = $v;
};
$var = 'Test Closure f1';
echo "var before array_walk: ($var)\n";
# this does work, var will be defined: unset($var);
$rc = array_walk_recursive($a, $f1, 'L', $var);
echo "rc = $rc, var after array_walk f1 with call by ref in parameter list: ($var)\n";
echo "We can only pass 1 extra parameter into the callback, f1 does not work\n";
echo '------------------------------', PHP_EOL;
/**
* the idea is to test if we have call by ref in a closure parameter
*/
$f2 = function ($v,$k, &$var) {
if ($k=='I') $var = $v;
};
$var = 'Test Closure f2';
echo "var before array_walk: ($var)\n";
$rc = array_walk_recursive($a, $f2, $var);
echo "rc = $rc, var after array_walk f2 with call by ref in parameter list: ($var)\n";
#echo "We can only pass 1 extra parameter into the callback, f1 does not work\n";
echo '------------------------------', PHP_EOL;
echo <<<EOD
Result for Closure as callback in array_walk:
We can pass variables by ref in the use() parameter list, and only there.
This is the way to return results.
The callback invocation supports one more variable or value, after value and key.
EOD
;
|