Per un po 'di tempo, ho utilizzato una funzione ricorsiva "tradizionale" per appiattire gli array multidimensionali comePass-by-reference che non funziona con parametri aggiuntivi per array_walk_recursive, a meno che non si tratti del riferimento pass-by deprecato per le chiamate
$baseArray = array(array('alpha'),
array('beta','gamma'),
array(),
array(array('delta','epsilon'),
array('zeta',array('eta',
'theta'
),
),
),
array('iota'),
);
in un semplice array 1-d.
Ieri sera, ho pensato di dare un'occhiata all'utilizzo di array_walk_recursive() per vedere se potevo renderlo più efficiente e più pulito.
Il mio primo tentativo non ebbe molto successo:
function flattenArray($arrayValue, $arrayKey, &$flatArray) {
$flatArray[] = $arrayValue;
}
$flattenedArray = array();
array_walk_recursive($baseArray,'flattenArray',$flattenedArray);
ho pensato che dovrebbe funzionare, ma tutto quello che ho ottenuto è stato una serie di errori:
Warning: Cannot use a scalar value as an array in C:\xampp\htdocs\arrayTest.php on line 16
e un risultato di:
array(0) { }
Tipo hinting nella mia funzione flattenArray() mi ha dato
Catchable fatal error: Argument 3 passed to flattenArray() must be an array, integer given in C:\xampp\htdocs\arrayTest.php on line 16
Utilizzando una chiusura ha dato risultati identici
L'unico modo ho potuto farlo funzionare (senza ricorrere all'utilizzo di una globale o statico per la mia flattenedArray) è stato utilizzando la chiamata in tempo pass-by-di riferimento:
function flattenArray($arrayValue, $arrayKey, $flatArray) {
$flatArray[] = $arrayValue;
}
$flattenedArray = array();
array_walk_recursive($baseArray,'flattenArray',&$flattenedArray);
che produce il risultato corretto
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" }
ma mi dà un avvertimento non-inaspettato
Deprecated: Call-time pass-by-reference has been deprecated in C:\xampp\htdocs\arrayTest.php on line 22
So che PHP è un linguaggio stravagante, ma questo sembra un po 'estremo. La documentazione mostra chiaramente che il primo parametro di array_walk_recursive è pass-by-reference, ma sembra che gli argomenti aggiuntivi possano essere pass-by-reference al momento della chiamata. Strano!
versione di PHP 5.3.8 è
Eventuali suggerimenti su come posso utilizzare array_walk_recursive per appiattire il mio allineamento correttamente, senza ottenere errori deprecate (oltre a deposito di un bug report).
EDIT
P.S.
Sono consapevole che posso aggirare questo problema utilizzando una chiusura:
$flattenedArray = array();
array_walk_recursive($baseArray, function($arrayValue, $arrayKey) use(&$flattenedArray){ $flattenedArray[] = $arrayValue; });
var_dump($flattenedArray);
ma come questo è necessario per una libreria che attualmente permette l'uso con PHP 5.2.0, non è una soluzione pratica di utilizzare un funzionalità che richiede una versione significativamente successiva di PHP
Posso vedere la logica, anche se non sono sicuro di essere d'accordo con esso ... l'argomento arrayValue viene passato alla funzione di callback per riferimento, consentendo di modificare i valori dell'array - cambio di funzione (& $ arrayValue, $ arrayKey) { \t $ arrayValue. = 'TEST'; } array_walk_recursive ($ baseArray, 'changer'); var_dump ($ baseArray); –
Il problema di corruzione della memoria mi sembra potenzialmente serio anche se .... non ne ho visto alcuna prova fino a quando non lo hai evidenziato –
Penso certamente che ci dovrebbe essere qualche nota formale che indica che la chiamata per riferimento non può essere usata con argomenti aggiuntivi nella funzione di callback come per call_user_func(), non solo qualsiasi commento che potrei aggiungere –