Reputation: 29434
I have made this little class:
class Analyzer {
public static function analyze($phrases) {
$sortedPhrases = array();
array_walk($phrases, array('self', 'splitByLength'), $sortedPhrases);
var_dump($sortedPhrases);
}
private static function splitByLength($item, $key, &$resArr) {
// line stolen from here: http://stackoverflow.com/a/4786840/603003
// thanks to arnaud576875 <http://stackoverflow.com/users/576875/arnaud576875>
$len = count( preg_split('#\PL+#u', $item, -1, PREG_SPLIT_NO_EMPTY) );
if (!isset($resArr[$len])) {
$resArr[$len] = array();
}
$resArr[$len][] = $item;
var_dump($resArr);
}
}
$phrases = array(
"I can't believe the great content",
"I can't understand the superior information",
"I can't comprehend the amazing data",
"I cannot analyze the amazing data",
"I haven't written to the amazing data"
);
Analyzer::analyze($phrases);
Executing the script results in the output below:
array (size=1)
7 =>
array (size=1)
0 => string 'I can't believe the great content' (length=33)
...
array (size=3)
7 =>
array (size=3)
0 => string 'I can't believe the great content' (length=33)
1 => string 'I can't understand the superior information' (length=43)
2 => string 'I can't comprehend the amazing data' (length=35)
6 =>
array (size=1)
0 => string 'I cannot analyze the amazing data' (length=33)
8 =>
array (size=1)
0 => string 'I haven't written to the amazing data' (length=37)
array (size=0)
empty
All outputs are actually correct except the last one which comes from Analyzer::analyze(). It seems that the variable $sortedPhrases
is somehow cleared after array_walk().
Upvotes: 1
Views: 1333
Reputation: 51950
While the third argument sent to the callback function cannot be a reference itself, it can contain references.
A different approach (to using objects or wrapping your callback in a closure) is to pass an array to the callback, containing a reference to the variable you wish to update. The wrapping array gets passed by-value, but all it contains is the referenced value that you want to change.
class Analyzer {
public static function analyze($phrases) {
// …
array_walk($phrases,
array('self', 'splitByLength'),
array(&$sortedPhrases));
// …
}
private static function splitByLength($item, $key, $extra_args) {
$resArr = &$extra_args[0];
// …
}
}
Upvotes: 2
Reputation: 16719
Take a better look at array_walk
's documentation page.
userdata
If the optional userdata parameter is supplied, it will be passed as the third parameter to the callback funcname.
That's the third parameter. It's not a reference, it's just a value that gets passed to your callback function.
One (of many) solutions to your problem is to use an object instead (objects are always passed by reference):
class Analyzer {
public static function analyze($phrases) {
$arrObj = new ArrayObject();
array_walk($phrases, array('self', 'splitByLength'), $arrObj);
var_dump($arrObj->getArrayCopy());
}
private static function splitByLength($item, $key, $arrObj) {
// line stolen from here: http://stackoverflow.com/a/4786840/603003
// thanks to arnaud576875 <http://stackoverflow.com/users/576875/arnaud576875>
$len = count( preg_split('#\PL+#u', $item, -1, PREG_SPLIT_NO_EMPTY) );
if (!isset($arrObj[$len])) {
$arrObj[$len] = array();
}
$arrObj[$len][] = $item;
var_dump($arrObj->getArrayCopy());
}
}
(it doesn't have to be an ArrayObject
, it can be a stdClass object with an array property, or create your own class if you want...)
Or you can wrap your call within an anonymous function if you really want to work with a reference:
$static = get_called_class();
array_walk($phrases, function($item, $key) use($static, &$sortedPhrases){
$static::splitByLength($item, $key, $sortedPhrases);
});
Upvotes: 5
Reputation: 124
Pretty sure this is wrong:
array_walk($phrases, array('self', 'splitByLength'), $sortedPhrases);
So, Try this:
$sortedPhrases = array_walk($phrases, 'splitByLength');
And return your values in $sortedPhrases
and don't use pass by reference (personal thing)
Upvotes: 1