Probleme mit array_walk_recursive
Christopher
- php
Hallo,
da das komplette Programm in PHP4 geschrieben ist, wollte ich die Kompatibilität erhalten und das UTF-( encoding über das bei php.net gefundene Skript relaisieren.
ALlerdings arbeitet die Funktion nicht wie gewünscht.
Das ist der aktuelle Quellcode:
function utf8_decode_array (&$value, &$key, $userdata = "") {
if(is_array($value)) {
array_walk_recursive2 ($value, 'utf8_decode_array');
} else {
$value = utf8_decode($value);
}
}
function array_walk_recursive2(&$input, $funcname, $userdata = "")
{
if (!is_callable($funcname))
{
return false;
}
if (!is_array($input))
{
return false;
}
foreach ($input AS $key => $value)
{
if (is_array($input[$key]))
{
array_walk_recursive2($input[$key], $funcname, $userdata);
}
else
{
$saved_value = $value;
if (!empty($userdata))
{
$funcname($value, $key, $userdata);
}
else
{
$funcname($value, $key);
}
if ($value != $saved_value)
{
$input[$key] = $value;
}
}
}
return true;
}
array_walk_recursive2 ($this->varToImport, utf8_decode_array);
Das encoding funktioniert relativ gut. Allerdings werden die Arrays in dem Array nicht umkodiert.
Ich finde den Fehler in dem vorhandenen Skript nicht. Das Problem taucht auch auf, wenn ich die vorgefertigte Funktion aus PHP5 nehmen.
Hat jemand eine Idee, wie ich die Arrays in dem Array auch noch bearneiten kann ?
Besten dank im vorraus.
Hi,
foreach ($input AS $key => $value)
{
if (is_array($input[$key]))
{
array_walk_recursive2($input[$key], $funcname, $userdata);
foreach arbeitet unter PHP 4 immer mit Kopien der Arrayelemente.
Du magst hier also beim Aufruf von array_walk_recursive2 den Parameter $input[$key] zwar durchaus per Referenz uebergeben - nutzt dir aber gar nix, weil der Wert *selber* lediglich eine Kopie darstellt, und somit keine Veraenderung des Originalwertes bewirken kann.
http://www.php.net/manual/en/control-structures.foreach.php:
Note: Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself.
In den Nutzerkommentaren sollten sich Hinweise finden, wie man das auch unter PHP 4 realisiert bekommt.
MfG ChrisB
Hi,
Du magst hier also beim Aufruf von array_walk_recursive2 den Parameter $input[$key] zwar durchaus per Referenz uebergeben - nutzt dir aber gar nix, weil der Wert *selber* lediglich eine Kopie darstellt
Nee, das war jetzt auch Bloedsinn - du uebergibst ja nicht $value, sondern $input[$key] ... hm, selber ratlos.
MfG ChrisB
Hi,
Du magst hier also beim Aufruf von array_walk_recursive2 den Parameter $input[$key] zwar durchaus per Referenz uebergeben - nutzt dir aber gar nix, weil der Wert *selber* lediglich eine Kopie darstellt
Nee, das war jetzt auch Bloedsinn - du uebergibst ja nicht $value, sondern $input[$key] ... hm, selber ratlos.
MfG ChrisB
Das Problem besteht ja auch nicht darin dass nichts passiert. Alle Elemente die sich direkt in dem Array befinden, werden geändert. Problematisch wird es mit den tieferliegenden Elementen.
Das Problem sind also die mehreren Dimensionen.
NACHTRAG:
Ich habe ein Objektorientierte Lösung gefunden, die angeblich funktionieren soll, nur bekomme ich sie nicht funktionierend angepasst. Dazu verstehe ich zu wenig von Objektorientierung:
private function array_walk_recursive(&$input) {
$funcname = array(&$this, $this->funcname);
if (!is_callable($funcname)) {
return false;
}
if (!is_array($input)) {
return false;
}
$this->depth++;
foreach (array_keys($input) AS $keyIdx => $key) {
$saved_value = $input[$key];
$saved_key = $key;
call_user_func_array($funcname, array(&$input[$saved_key], &$key));
if ($input[$saved_key] !== $saved_value || $saved_key !== $key) {
$saved_value = $input[$saved_key];
unset($input[$saved_key]);
$input[$key] = $saved_value;
}
if (is_array($input[$key])) {
if (!$this->array_walk_recursive($input[$key], $funcname)) return false;
$this->depth--;
}
}
return true;
}
Vielleicht weiß jemand wie die Funktion ohne Objektorientierung aussehen muss und hilft mal kurz weiter.
Hallo
function utf8_decode_array (&$value, &$key, $userdata = "") {
if(is_array($value)) {
array_walk_recursive2 ($value, 'utf8_decode_array');
} else {
$value = utf8_decode($value);
}
}
$key und $userdata werden innerhalb deiner Funktion nicht weiter verwendet. Sofern es sich bei deinem hier geposteten Code nicht um eine abgespeckte Version handel, würde ich es einfach weg lassen. PHP stört sich übrigens nicht dran, wenn du mehr Parameter übergibst als erwartet (nur weniger dürfen es natürlich nicht sein). Gleiches gilt für deine If-Abfrage. Die macht bei dem vorliegenden Code einfach keinen Sinn, da du das ganze ja zum Anfang direkt array_walk_recursive2 aufrufst. Der Sinn hinter der If-Abfrage ist richtig und wichtig, dann sei aber auch so konsequent und verwende es auch wie geplant indem du deinen ersten Funktionsaufruf über utf8_decode_array machst.
if (!empty($userdata))
{
$funcname($value, $key, $userdata);
}
else
{
$funcname($value, $key);
}
Üerflüssiges if, vorrausgesetzt du hast keine Funktionen, die als dritten Parameter zwingend NULL erwarten.
if ($value != $saved_value)
{
$input[$key] = $value;
}
Beim rekursiven Aufruf oben so schön gelöst und hier dann so falsch gemacht. Verwende besser gleich $funcname($index[$value], $key, $userdata). Dadurch sparst du dir das kopieren von $value und ein if.
array_walk_recursive2 ($this->varToImport, utf8_decode_array);
Wie schon oben gesagt: sei hier dann wenigstens so konsequent und verwende direkt utf8_decode_array. Zudem fehlen hier bei utf8_decode_array die Anführungszeichen, du willst ja schließlich einen String übergeben.
Hier nochmal alles schön zusammengefasst:
function utf8_decode_array (&$value) {
if(is_array($value)) {
array_walk_recursive2 ($value, 'utf8_decode_array');
} else {
$value = utf8_decode($value);
}
}
function array_walk_recursive2(&$input, $funcname, $userdata = "") {
if (!is_callable($funcname) || !is_array($input)) {
return false;
}
foreach($input as $key=>$value) {
if (is_array($value)) {
array_walk_recursive2($input[$key], $funcname, $userdata);
} else {
$funcname($input[$key], $key, $userdata); // was du bei der Zielfunktion mit $key anfangen willst versteh ich zwar nicht, aber du wirst schon wissen was du machst
}
}
return true;
)
utf8_decode_array($this->varToImport);
_Wichtig:_ Dabei handelt es sich nur um optische Verbesserungen, der Fehler in deinem Code muss woanders liegen. Poste doch mal was $this->varToImport vor und nach dem Funktionsaufruf beinhaltet. Vieleicht hilft das ja irgendwie weiter.