Od jakiegoś czasu używam "tradycyjnej" funkcji rekursywnej do spłaszczania wielowymiarowych tablic taki jakFunkcja pass-by-reference nie działa z dodatkowymi parametrami dla array_walk_recursive, chyba że jest to przestarzałe odwołanie do czasu wywołania
$baseArray = array(array('alpha'),
array('beta','gamma'),
array(),
array(array('delta','epsilon'),
array('zeta',array('eta',
'theta'
),
),
),
array('iota'),
);
na prostą tablicę 1-d.
Ostatniej nocy pomyślałem, że przyjrzę się użyciu array_walk_recursive(), aby sprawdzić, czy mogę sprawić, że będzie on bardziej wydajny i czyściejszy.
Moja pierwsza próba nie była bardzo udana:
function flattenArray($arrayValue, $arrayKey, &$flatArray) {
$flatArray[] = $arrayValue;
}
$flattenedArray = array();
array_walk_recursive($baseArray,'flattenArray',$flattenedArray);
myślałem powinno działać, ale wszystko, co mam była seria błędów:
Warning: Cannot use a scalar value as an array in C:\xampp\htdocs\arrayTest.php on line 16
i wynikiem:
array(0) { }
Podpowiedzi typów w funkcji flattenArray() dały mi
Catchable fatal error: Argument 3 passed to flattenArray() must be an array, integer given in C:\xampp\htdocs\arrayTest.php on line 16
Korzystanie zamknięcie dało identyczne wyniki
Jedynym sposobem mogę zmusić go do pracy (bez uciekania się do korzystania z globalną lub statyczną dla mojego flattenedArray) był za pomocą call-czas pass-by-reference:
function flattenArray($arrayValue, $arrayKey, $flatArray) {
$flatArray[] = $arrayValue;
}
$flattenedArray = array();
array_walk_recursive($baseArray,'flattenArray',&$flattenedArray);
która produkuje poprawny wynik
array(9) { [0]=> string(5) "alpha" [1]=> string(4) "beta" [2]=> string(5) "gamma" [3]=> string(5) "delta" [4]=> string(7) "epsilon" [5]=> string(4) "zeta" [6]=> string(3) "eta" [7]=> string(5) "theta" [8]=> string(4) "iota" }
ale daje mi nie-nieoczekiwane ostrzeżenie
Deprecated: Call-time pass-by-reference has been deprecated in C:\xampp\htdocs\arrayTest.php on line 22
Wiem, PHP jest językiem, dziwaczne, ale to wydaje się być nieco ekstremalne. Dokumentacja wyraźnie pokazuje, że pierwszym parametrem dla array_walk_recursive jest pass-by-reference, ale wydaje się, że dodatkowe argumenty mogą być przekazywane tylko przez odniesienie w czasie połączenia. Dziwne!
wersja PHP 5.3.8
Wszelkie sugestie, w jaki sposób mogę korzystać array_walk_recursive spłaszczyć moją tablicę poprawnie, bez uzyskiwania nieaktualnych błędów (oprócz złożenia raportu o błędzie).
EDIT
PS:
Zdaję sobie sprawę, że mogę ominąć ten problem używając Zamknięcie:
$flattenedArray = array();
array_walk_recursive($baseArray, function($arrayValue, $arrayKey) use(&$flattenedArray){ $flattenedArray[] = $arrayValue; });
var_dump($flattenedArray);
ale jak to jest wymagane dla biblioteki, która obecnie pozwala korzystać z PHP 5.2.0, nie jest praktycznym rozwiązaniem, aby użyć funkcja wymagająca znacznie późniejszej wersji PHP
Widzę logikę, chociaż nie jestem pewna, czy się z nią zgadzam ... argument arrayValue jest przekazywany do funkcji wywołania zwrotnego przez odniesienie, umożliwiając zmianę wartości tablicowych - zmieniacz funkcji (& $ arrayValue, $ arrayKey) { \t $ arrayValue. = 'TEST'; } array_walk_recursive ($ baseArray, 'changer'); var_dump ($ baseArray); –
Problem z uszkodzeniem pamięci uderza mnie jako potencjalnie poważny, chociaż ... nie widziałem żadnego dowodu, dopóki go nie podświetliłeś. –
Na pewno myślę, że powinna istnieć jakaś formalna uwaga oznaczająca, że nie można użyć wywołania referencyjnego z dodatkowymi argumentami w funkcji wywołania zwrotnego jak dla funkcji call_user_func(), a nie tylko z komentarzem, który mógłbym dodać: –