justanumber44
Goto Top

PHP - Dynamische Keys für multidimensionale Arrays

Hallo mal wieder. Ich suche eine "bessere" Möglichkeit, gegebene Schlüssel an gegebene Positionen in Arrays zu setzen.
Das Eingangsformat sieht so aus, dass ich mehrere ineinander liegende Arrays habe, und diese Inhalte dann durch neuere ersetzen möchte.
Das heißt im Beispiel:

Hab ich $profile["fields"]["public"]["skype_id"] = "test123"
Möchte ich $profile["fields"]["public"]["skype_id"] = "user123"

Das währe ja kein Problem, doch leider weiß mein PHP Script per Ajax nur eine Übermittlung mit den Positionen und den Werten bekommt, das sieht dann so aus:
Bekommt Position als $position -> ["fields"]["public"]["skype_id"]
Bekommt den Wert als $wert -> user123

Theoretisch: $profile$position = $wert

Das geht aber logischer weise nicht. Mein Ansatz war dahingehend folgender:


 
<?php

$json_input = '{  
    "fields|private|skype": "user123",  
    "fields|public|twitter": "http://twitter.com/user"  
}';  

$input = json_decode($json_input, true);

while (list($key, $value) = each($input)) {
    
	$position = str_replace("|",'"]["', $key);  
	$position = '["' . $position . '"]';  
		
	
	eval("\$dome_profile$position = '$value';");  
	
}

echo "<pre>";  
var_dump($dome_profile);
echo "<br>";  
print_r($dome_profile);
echo "</pre>";  

?>

Output:
array(1) {
["fields"]=>
array(2) {
["private"]=>
array(1) {
["skype"]=>
string(7) "user123"
}
["public"]=>
array(1) {
["twitter"]=>
string(23) "http://twitter.com/user"
}
}
}

Array
(
[fields] => Array
(
[private] => Array
(
[skype] => user123
)
[public] => Array
(
[twitter] => http://twitter.com/user
)
)
)
Nun ist meine Frage: Gibt es eine "schönere" und bessere Lösung, und falls nicht: Packt eval das überhaupt, wenn ich da z.B. Bilder (als Base64) setze?

Die Daten kommen als Array aus der Datenbank, werden dann vom Nutzer bearbeitet, übertragen, gesetzt und wieder in die Datenbank geladen, das Funktioniert alles, auch der Ansatz da oben.

Content-ID: 275365

Url: https://administrator.de/contentid/275365

Ausgedruckt am: 24.11.2024 um 02:11 Uhr

Guenni
Guenni 29.06.2015 aktualisiert um 16:45:52 Uhr
Goto Top
Hi justanumber44,

also um das mal nach zu vollziehen:

Zitat von @justanumber44:
. . .
Das Eingangsformat sieht so aus, dass ich mehrere ineinander liegende Arrays habe, und diese Inhalte dann durch neuere ersetzen möchte.
. . .
Die Daten kommen als Array aus der Datenbank, werden dann vom Nutzer bearbeitet, übertragen, gesetzt und wieder in die
Datenbank geladen, das Funktioniert alles, auch der Ansatz da oben.
. . .


Wenn doch die Daten sowieso als Array aus einer DB/Tabelle kommen, warum bastelst du dir dann aus einem String, der aus drei Begriffen

getrennt durch "|", besteht . . .

$json_input = '{  
    "fields|private|skype": "user123",  
    "fields|public|twitter": "http://twitter.com/user"  
}';  

. . . erstmal umständlich ein Array und machst dann mit eval eine fragwürdige (siehe http://php.net/manual/de/function.eval.php) Wertezuweisung??


Zum Erstellen eines Arrays gibts doch die gleichnamige Funktion array([string key] => value).

$input = array("fields" => array("private" => array("skype" => "test123"),  
	 "public" => array("twitter" => "http://www.twitter.com/user")));  

Eine neue Wertezuweisung ist doch dann leicht.

$input["fields"]["private"]["skype"] = "user123";  

Und hat ein User eine zweite Skype-ID (Zweithandy), so "hängst" du diese einfach an ["private"] dran.

$input["fields"]["private"]["skype2"] = "user784392";  


Das hier . . .

Das währe ja kein Problem, doch leider weiß mein PHP Script per Ajax nur eine Übermittlung mit den Positionen und den Werten bekommt, das sieht dann so aus:

Bekommt Position als $position -> ["fields"]["public"]["skype_id"]
Bekommt den Wert als $wert -> user123

Theoretisch: $profile$position = $wert

Das geht aber logischer weise nicht.

. . . müsstest du auch mal näher erläutern.


Auch theoretisch: Eine Tabelle wird abgefragt, die Daten landen zur Bearbeitung in einem Formular. Dann werden die neuen Daten zurückgeschrieben.

Was funktioniert denn genau bei der Übermittlung bzw. Auswertung via Ajax nicht?

Vielleicht kommen wir da ja weiter.


Gruß
Günni
justanumber44
justanumber44 29.06.2015, aktualisiert am 30.06.2015 um 23:39:59 Uhr
Goto Top
Naja, es ist eigentlich so, dass in einem PHP Dokument automatisiert Einträge erstellt werden, in einer Each Funktion. Übergeben wird, eben via json, was wo hin gehört. Ich muss eben in ein vorhandenes Array zu den passenden Positionen die Einträge speichern:

Client: "test" -> fields -> public -> skype_id - Der sagt also, wo es hin geht
Server: $input["fields"]["public"]["skype_id"] -> "test"

Das Problem ist, das ich leider nicht einfach sagen kann, wo er den Wert einspeichern soll außer eval

Ich muss anhand eines Strings die Position eines Arrays bestimmen, um dort schlussendlich den Wert zu sichern
Larmina
Larmina 30.06.2015 aktualisiert um 18:03:07 Uhr
Goto Top
Hi,
also wenn ich das Json richtig verstanden habe, dann sind da ja zwischen jedem Wert die '|' dazwischen, die du per str_replace trennst.
Warum machst du dann nicht einfach ein 4D Array, das aus einem Zähler für den Eintrag, den Kennzeichnern und dem Wert besteht?
Das ließe sich wunderbar mit explode für '|' regeln.

also quasi
<?php
$i = 0;
foreach ($jsoninput as $value)
{
    $typ_temp = explode('|', $value);  
    $dim1 = $typ_temp;
    $dim2 = $typ_temp[1];
    $dim3 = $typ_temp[2];
    $array[$i][$dim1][$dim2][$dim3] = $Wertdendualswerthast;
    $i++;
 }
?>
Wird halt ein klein wenig abartig wenn du dann noch Sortierungen machen willst, weil ab 3 Dimensionen steig ich da einfach aus geistig :D

Liebe Grüße und viel Erfolg

Larmina
justanumber44
justanumber44 30.06.2015 aktualisiert um 23:43:48 Uhr
Goto Top
Zitat von @Larmina:

Hi,
also wenn ich das Json richtig verstanden habe, dann sind da ja zwischen jedem Wert die '|' dazwischen, die du per
str_replace trennst.
Warum machst du dann nicht einfach ein 4D Array, das aus einem Zähler für den Eintrag, den Kennzeichnern und dem Wert
besteht?
Das ließe sich wunderbar mit explode für '|' regeln.

also quasi
> <?php
> $i = 0;
> foreach ($jsoninput as $value)
> {
>     $typ_temp = explode('|', $value);  
>     $dim1 = $typ_temp;
>     $dim2 = $typ_temp[1];
>     $dim3 = $typ_temp[2];
>     $array[$i][$dim1][$dim2][$dim3] = $Wertdendualswerthast;
>     $i++;
>  }
> ?>
> 
Wird halt ein klein wenig abartig wenn du dann noch Sortierungen machen willst, weil ab 3 Dimensionen steig ich da einfach aus
geistig :D

Liebe Grüße und viel Erfolg

Larmina

Weil die Länge der Arrays leider nicht fest definiert ist, deshalb auch dynamisch. Glücklicher weise muss ich nichts sortieren :D
Aber meine zweite Ansatz Vermutung ging in die dynamischen Variablen, die PHP auch als Funktion anbietet, hab dabei nur nichts passendes gefunden

Als Eingangsformat habe ich eben diese "|" getrennte Schreibweise gewählt, um direkt wissen zu können, wo meine Werte hin sollen. Diese Angabe kann nur per json kommen, da dahinter haufenweise Dynamisch erstellte Eingabefelder liegen, die bei Änderung eben ihren neuen Wert und die Position, für die dieser Wert gedacht ist weitergeben, das was das PHP Script dann per Ajax bekommt.
Mit freundlichen Grüßen Jonas
Larmina
Larmina 01.07.2015 aktualisiert um 10:30:10 Uhr
Goto Top
Hi Jonas,
wenn du es komplett Dynamisch haben willst, dann hab ich dir hier grade eine kleine Funktion geschrieben.

Du musst dann halt den Wert den du am Ende übergeben willst auch als Arraykey setzen, und dann die arrays durchlaufen.
Oder du dröselst dir einen Weg in der Funktion noch einen Wert zu übergeben, was ich jetzt ohne größeren Aufwand nicht hinbekommen habe.

function array_add_dimensions($array, $arr_dims)
{ 
	if(count($arr_dims) === 0)
	{ 
		
		return $array; 
	} 
	$dim = array_shift($arr_dims);
	$array[$dim] = array();
	$array[$dim] = array_add_dimensions($array[$key], $arr_dims);
	return $array; 
} 

$arr_dims = array('profil','private','skypeid','foobar',); // Hier fügst du die Werte ein die vom JSON kommen, geht ja auch dynamisch via explode und foreach.  

$array = array(); 
print_r(array_add_dimensions($array, $arr_dims));


Liebe Grüße
Larmina
justanumber44
justanumber44 01.07.2015 um 21:42:09 Uhr
Goto Top
Zitat von @Larmina:

Hi Jonas,
wenn du es komplett Dynamisch haben willst, dann hab ich dir hier grade eine kleine Funktion geschrieben.

Du musst dann halt den Wert den du am Ende übergeben willst auch als Arraykey setzen, und dann die arrays durchlaufen.
Oder du dröselst dir einen Weg in der Funktion noch einen Wert zu übergeben, was ich jetzt ohne größeren
Aufwand nicht hinbekommen habe.

> function array_add_dimensions($array, $arr_dims)
> { 
> 	if(count($arr_dims) === 0)
> 	{ 
> 		
> 		return $array; 
> 	} 
> 	$dim = array_shift($arr_dims);
> 	$array[$dim] = array();
> 	$array[$dim] = array_add_dimensions($array[$key], $arr_dims);
> 	return $array; 
> } 
> 
> $arr_dims = array('profil','private','skypeid','foobar',); // Hier fügst du die Werte  
> ein die vom JSON kommen, geht ja auch dynamisch via explode und foreach.
> 
> $array = array(); 
> print_r(array_add_dimensions($array, $arr_dims));
> 
> 


Liebe Grüße
Larmina

Okay, das ist auf jeden Fall mal ein cooler Ansatz, krieg nur keinen Wert gesetzt, um am Schluss einen String zu setzen. Ist auch ein kleiner Fehler drinnen, was die Variable $key angeht. Trotzdem Danke, werd mal schauen, was da noch möglich ist

Mfg Jonas
Larmina
Larmina 02.07.2015 um 10:50:59 Uhr
Goto Top
Hi,
ja das $key muss mir entschlüpft sein ^.^

Normalerweise heißt bei mir im Arraybereich die Variable immer $key, nur wollte ich es ausnahmsweise mal besonderst nachvollziehbar machen ;)

Liebe Grüße
Larmina
Guenni
Guenni 11.07.2015 um 17:21:43 Uhr
Goto Top
Zitat von @justanumber44:

Naja, es ist eigentlich so, dass in einem PHP Dokument automatisiert Einträge erstellt werden, in einer Each Funktion.
Übergeben wird, eben via json, was wo hin gehört. Ich muss eben in ein vorhandenes Array zu den passenden Positionen die
Einträge speichern:

Client: "test" -> fields -> public -> skype_id - Der sagt also, wo es hin geht
Server: $input["fields"]["public"]["skype_id"] -> "test"

Das Problem ist, das ich leider nicht einfach sagen kann, wo er den Wert einspeichern soll außer eval

Ich muss anhand eines Strings die Position eines Arrays bestimmen, um dort schlussendlich den Wert zu sichern


Hi justanumber44,

also irgendwie erschließt sich mir nicht der Sinn von deinem Vorhaben.

Es werden . . . in einem PHP Dokument automatisiert Einträge erstellt . . .

In einer Each Funktion ???. Erklärung bitte.


Übergeben wird, eben via json, was wo hin gehört.

Client: "test" -> fields -> public -> skype_id - Der sagt also, wo es hin geht


Der sagt also, wo es hin geht. Wer ist "Der"?. Wie und wo sagt "Der" dir, "wo es hin geht"?

Erkläre das doch auch mal genauer. Was wird wie via json übergeben ?? Vielleicht postest du mal ein Script ??


Das Problem ist, das ich leider nicht einfach sagen kann, wo er den Wert einspeichern soll außer eval
Ich muss anhand eines Strings die Position eines Arrays bestimmen, um dort schlussendlich den Wert zu sichern

Das widerspricht sich doch irgendwie, oder? Du kannst nicht sagen, wo ein Wert gespeichert werden soll,

bestimmst aber anhand eines Strings, dass ein Wert dann doch irgendwo gespeichert wird.


Was du an Larminas Funktionsergebnis als "coolen Ansatz" beschreibst . . .

Array
(
[profil] => Array
(
[private] => Array
(
[skypeid] => Array
(
[foobar] => Array
(
[Noch_ein_Array] => Array
(
[Und_noch_ein_Array] => Array
(
[Ein_letztes_Array] =>
)

)

)

)

)

)

)

Du willst doch nicht ernsthaft sagen, dass du das in einer DB-Tabelle speicherst (speichern willst)???


Ein Abfrageergebnis einer Datenbank ist in der Regel immer ein Array. Und in der Regel bestehen die Array-Schlüssel

aus den Namen der jeweiligen Tabellenspalten. Also weiß ich doch anhand der Array-Schlüssel, auch wieder in der Regel,

wo ich Werte in eine Tabelle zurückschreibe. Und auch wenn mir die Werte via json übergeben werden, gibts auch hier für

"coole Ansätze", Elementpositionen in einem Array zu finden und zu beschreiben.


Deshalb auch meine Frage im ersten Kommentar: Was funktioniert denn genau bei der Übermittlung bzw. Auswertung via Ajax nicht?


Gruß
Günni
justanumber44
justanumber44 11.07.2015 aktualisiert um 17:49:19 Uhr
Goto Top
Zitat von @Guenni:

> Zitat von @justanumber44:
>
> Naja, es ist eigentlich so, dass in einem PHP Dokument automatisiert Einträge erstellt werden, in einer Each Funktion.
> Übergeben wird, eben via json, was wo hin gehört. Ich muss eben in ein vorhandenes Array zu den passenden
Positionen die
> Einträge speichern:
>
> Client: "test" -> fields -> public -> skype_id - Der sagt also, wo es hin geht
> Server: $input["fields"]["public"]["skype_id"] -> "test"
>
> Das Problem ist, das ich leider nicht einfach sagen kann, wo er den Wert einspeichern soll außer eval
>
> Ich muss anhand eines Strings die Position eines Arrays bestimmen, um dort schlussendlich den Wert zu sichern


Hi justanumber44,

also irgendwie erschließt sich mir nicht der Sinn von deinem Vorhaben.

> Es werden . . . in einem PHP Dokument automatisiert Einträge erstellt . . .

In einer Each Funktion ???. Erklärung bitte.


> Übergeben wird, eben via json, was wo hin gehört.
>
> Client: "test" -> fields -> public -> skype_id - Der sagt also, wo es hin geht


Der sagt also, wo es hin geht. Wer ist "Der"?. Wie und wo sagt "Der" dir, "wo es hin
geht"
?

Erkläre das doch auch mal genauer. Was wird wie via json übergeben ?? Vielleicht postest du mal ein Script ??


> Das Problem ist, das ich leider nicht einfach sagen kann, wo er den Wert einspeichern soll außer eval
> Ich muss anhand eines Strings die Position eines Arrays bestimmen, um dort schlussendlich den Wert zu sichern

Das widerspricht sich doch irgendwie, oder? Du kannst nicht sagen, wo ein Wert gespeichert werden soll,

bestimmst aber anhand eines Strings, dass ein Wert dann doch irgendwo gespeichert wird.


Was du an Larminas Funktionsergebnis als "coolen Ansatz" beschreibst . . .

Array
(
[profil] => Array
(
[private] => Array
(
[skypeid] => Array
(
[foobar] => Array
(
[Noch_ein_Array] => Array
(
[Und_noch_ein_Array] => Array
(
[Ein_letztes_Array] =>
)

)

)

)

)

)

)

Du willst doch nicht ernsthaft sagen, dass du das in einer DB-Tabelle speicherst (speichern willst)???


Ein Abfrageergebnis einer Datenbank ist in der Regel immer ein Array. Und in der Regel bestehen die Array-Schlüssel

aus den Namen der jeweiligen Tabellenspalten. Also weiß ich doch anhand der Array-Schlüssel, auch wieder in der Regel,

wo ich Werte in eine Tabelle zurückschreibe. Und auch wenn mir die Werte via json übergeben werden, gibts auch hier
für

"coole Ansätze", Elementpositionen in einem Array zu finden und zu beschreiben.


Deshalb auch meine Frage im ersten Kommentar: Was funktioniert denn genau bei der Übermittlung bzw. Auswertung via Ajax
nicht?



Gruß
Günni


Zur einfachen Erklärung: Ich nutze Twig (Template Engine) zur Erstellung von Eingabefeldern, welche in der Datenbank definiert sind, also was das für ein Feld ist, wo es dazu gehört, um diese dann per Ajax an ein PHP Script weiter zu geben, um diese dann als Arrays zu speichern.

Ja ich speicher diese Daten als Arrays. Nachdem MySQL und seine Anhänger schon seit Jahren ein bisschen aus der Mode gekommen sind, dabei leider auch sehr Performance fressend, und kaum Funktionen bieten, speicher ich die Inhalte im json Format in einer CouchDB

Die Speicherung ist eben spezieller: Die Seite, die aufgerufen wird, erstellt mit Twig in einer Schleife alle Eingabefelder, so wie sie in der Datenbank definiert wurden, und gibt ihnen als Information auch noch den Ort mit, wo der Wert gespeichert werden soll. Ändert der Benutzer den Inhalt eines der Felder, wird dessen Inhalt und der Speicherort in ein Array geschrieben und beim speichern an das PHP Script gesendet, welches die neuen Wert eben zu den alten hinzufügen soll.

Meine Funktion übernimmt diese Aufgabe ansich ja, aber mir gefällt die Umsetzung mit Eval nicht, da dort vom Nutzer Texte eingetragen werden könnten, die PHP Automatisch interpretieren würde, ein offenes Sicherheitsrisiko. Ebenfalls bin ich mir nicht sicher, ob Eval da nicht Probleme mit der Länge der Inhalte bekommen könnte, oder mit Sonderzeichen.

Schlussendlich suche ich nach einer Möglichkeit, wie beim Verzeichniswechsel, in einem Array vor zu wandern, wie als würde ich versuchen von der Festplatte in einen bestimmten, mir bekannten Unterordner zu gelangen, um dort was zu speichern, nur eben auf ein Array bezogen, das bereits befüllt ist.

Mit freundlichen Grüßen Jonas

Edit: Stellt euch einfach sowas wie eine cd Funktion in der Konsole vor, nur für Arrays
Guenni
Lösung Guenni 14.07.2015, aktualisiert am 29.07.2015 um 22:15:42 Uhr
Goto Top
Hi justanumber44,

dauert i.M. immer etwas, bis ich mal zum Antworten komme.

Schlussendlich suche ich nach einer Möglichkeit, wie beim Verzeichniswechsel, in einem Array vor zu wandern, wie als würde ich versuchen von der Festplatte in einen

bestimmten, mir bekannten Unterordner zu gelangen, um dort was zu speichern, nur eben auf ein Array bezogen, das bereits befüllt ist.

Zum Ändern eines Wertes könntest du viell. die Function array_walk_recursive verwenden??

<?php 
$input = array("fields" => array("private" => array("skype" => "test123"),  
	 "public" => array("twitter" => "http://www.twitter.com/heinz")));  

/* Callback zur Ausgabe */
function array_print($item, $key){
 echo "$key = $item<br>";  
}

/* Callback zum Ämdern */
function array_alter(&$item, $key, $user_data){
 if($key == key($user_data)){
  $item = $user_data[key($user_data)];
 }
}

echo "<h4>Vorher . . . </h4>";  
/* Funktionsaufruf mit Callback zur Ausgabe*/
array_walk_recursive($input, 'array_print');  

/*
* Neue Daten
*/
$data_neu = array("skype" => "user456");  

/* Oder . . .  */
// $data_neu = array("twitter" => "http://www.twitter.com/willi"); 


/* Funktionsaufruf mit Callback zum Ändern */
array_walk_recursive($input, 'array_alter', $data_neu);  

echo "<h4>Nachher . . . </h4>";  
/* Funktionsaufruf mit Callback  zur Ausgabe */
array_walk_recursive($input, 'array_print');  
?>

Geht aber, glaub' ich, wirklich nur zum Ändern von bestehenden Werten. Die Schlüssel fields, private, public z.B. werden gar nicht ausgegeben.

Wenn du hier PHP-Manual im Suchfeld array eingibst, so werden da noch aufgelistet . . .

- ArrayAccess
- ArrayIterator
- ArrayObject

Eventuell wäre da noch was dabei, was dir hilft, Arrays zu händeln. Hab' ich mir aber auch noch nie genauer angeguckt.

Gruß
Günni

PS.:

Sowas ähnliches wie cd auf der Konsole für Arrays gibts eigentlich schon.

current() — Liefert das aktuelle Element eines Arrays
end() - Positioniert den internen Zeiger eines Arrays auf dessen letztes Element
key() - Liefert einen Schlüssel eines Arrays
each() - Liefert das aktuelle Paar (Schlüssel und Wert) eines Arrays und rückt den Arrayzeiger vor
prev() - Setzt den internen Zeiger eines Arrays um ein Element zurück
reset() - Setzt den internen Zeiger eines Arrays auf sein erstes Element
next() - Rückt den internen Zeiger eines Arrays vor

Geht aber leider nur, soweit ich das probiert habe, auf einer Dimension in einem Array.