(mehrdimensionales) Array; explode

CoverUnder

Mitglied
Hallo,

einmal mehr wäre ich über eine Gedankenstütze bzw. einen Tipp sehr dankbar.

Ich habe eine Textarea, in die Daten nach einem bestimmten Schema hinein kommen, die mittels $_POST übermittelt werden. Der Inhalt der $_POST sieht in etwa so aus:

Code:
10001;Name;112;20;225;Ja
10002;Name ABC;120;40;153;Ja
10003;Name XYZ AB;129;0;13;Nein

Zuerst einmal muss ich die Zeilen splitten, denn jede Zeile entspricht einem Datensatz. Das habe ich so gemacht:

PHP:
$trim = trim($_POST['werte']);
$zeile = explode("\n", $trim);

Nun kommt der knifflige Part, wo ich momentan hänge:
$zeile[0] beinhaltet jetzt zum Beispiel "10001;Name;112;20;225;Ja"

Jetzt möchte ich die einzelnen Werte noch spalten und nach dem ; trennen. Mit Explode ein Array nochmals zu trennen funktioniert leider nicht, also suche ich nach einer Alternative. Was ich im Endeffekt brauchte, ist wohl ein mehrdimensionales Array... so dass ich die Werte der Zeilen einzeln ansprechen kann.

Zur Erklärung, weshalb ich das so haben möchte und zum Verständnis:
Jede Zeile entspricht einem Datensatz in der DB. Der erste Wert ist dabei die ID, die nachfolgenden Werte sind Daten für Spalten. Ich möchte die Werte aus der Datenbank durch die Werte aus diesem Formular/Script ersetzen, also ein SQL Update machen.

Hat jemand einen Tipp für mich? Ich wäre wirklich sehr dankbar für jeden Hinweis und jede Hilfestellung.
 
Dazu müsstest du über alle Zeilen loopen und diese einzeln exploden. Das Resultat kannst du an ein Array anhängen:

PHP:
$zeilen = explode("\n", $trim);
$werte_array=array();
foreach($zeilen as $zeile)
{
  $werte_array[] = explode(';', $zeile);
}
// Zur Kontrolle
var_dump($werte_array);
 
Du könntest auch gleich die built-in [phpf]str_getcsv[/phpf]-Funktion benutzen:
PHP:
$trim = trim($_POST['werte']);
$lines = explode("\n", $trim);

foreach ($lines as $line) {
  $data[] = str_getcsv($trim, ';');
}
Ist jetzt auch kein so großer Unterschied, außer natürlich bei großen Datenmengen, da die Funktion nativ in C implementiert wurde.
 
Wow, vielen Dank für die rasche Reaktion!

werte_array sieht nun so aus:

Code:
array(3) 
{ [0]=> array(6) 
{ [0]=> string(5) "10001" [1]=> string(4) "Name" [2]=> string(3) "112" [3]=> string(2) "20" [4]=> string(3) "225" [5]=> string(3) "Ja " } 

[1]=> array(6)
{ [0]=> string(5) "10002" [1]=> string(8) "Name ABC" [2]=> string(3) "120" [3]=> string(2) "40" [4]=> string(3) "153" [5]=> string(3) "Ja " } 

[2]=> array(6) 
{ [0]=> string(5) "10003" [1]=> string(11) "Name XYZ AB" [2]=> string(3) "129" [3]=> string(1) "0" [4]=> string(2) "13" [5]=> string(4) "Nein" } 
}

Von den Werten her stimmts soweit auf jeden Fall :-)

Da mein Wissen bzgl. (mehrdimensionale) Arrays noch in den Kinderschuhen steckt, würde ich die nächsten Schritte gerne noch durchbesprechen.

Den ersten Wert rufe ich nun mit werte_array[0][0] auf - das entspricht dann "10001" - sehe ich das richtig?
Dann brauche ich ein SQL Update, das alle Datensätze durcharbeitet. Dabei dachte ich an eine for-Schleife, da ich die [zahl] Werte ja immer um eines hochsetzen muss... also vielleicht werte_array[$i][0]. So in die Richtung?

Kurz skizziert:
PHP:
for ($i = 0; $i++)
{
    $sql = "SQL UPDATE tabelle SET feld1 = $werte_array[$i][1], feld2 = $werte_array[$i][2] WHERE id = $werte_array[$i][0]";
}

Würde das so in der Art funktionieren?

----

EDIT: Sorry, ich habe die zweite Antwort erst jetzt gesehen, nachdem ich gepostet habe. Vielen Dank! Ich werde mal beide Varianten ausprobieren!
 
Zuletzt bearbeitet:
Jain. Eine for-Schleife kannst du verwenden, aber foreach wäre hier wohl einfacher, da für die for-Schleife ein oberes Limit (Anzahl Zeilen) benötigt wird. Ich würde es so machen:

PHP:
foreach($werte_array as $werte)
{
  $sql = "SQL UPDATE tabelle SET feld1 = $werte[1], feld2 = $werte[2] WHERE id = $werte[0]"; 
}

Aber es geht noch eleganter. Die Schleife über alle Zeilen hast du bereits. Also kannst den Code so vereinfachen:

PHP:
$zeilen = explode("\n", $trim);

foreach($zeilen as $zeile)
{
  $werte = explode(';', $zeile);
  $sql = "SQL UPDATE tabelle SET feld1 = $werte[1], feld2 = $werte[2] WHERE id = $werte[0]"; 
}

Offtopic:
Du könntest auch gleich die built-in [phpf]str_getcsv[/phpf]-Funktion benutzen:
Ist jetzt auch kein so großer Unterschied, außer natürlich bei großen Datenmengen, da die Funktion nativ in C implementiert wurde.

Weil es mich interessiert hat: Habe die PLZ-DB von hier heruntergeladen und ein kleines Script gebastelt:

PHP:
<?php
$lines = file_get_contents('plz_de.csv');

$lines = explode("\r\n", $lines);
$s = microtime(true);
foreach($lines as $line)
{
	$w = explode(';', $line);
}
$e = microtime(true);
echo "explode: " . ($e - $s). " seconds<br/>";

$s = microtime(true);
foreach($lines as $line)
{
	$w = str_getcsv($line, ';');
}
$e = microtime(true);
echo "str_getcsv: " . ($e - $s). " seconds<br/>";

Ergebnis:
Code:
explode: 0.02018404006958 seconds
str_getcsv: 0.1623740196228 seconds
 
Vielen herzlichen Dank! Es funktioniert!

Und auch für den interessanten Vergleich der beiden Möglichkeiten. Dann bleibe ich bei explode.

Entschuldigt, dass ich den bereits erledigten Thread nun nochmals raufhole, aber es ist gerade noch eine Kleinigkeit aufgetreten, wo ich mit meinem Latein am Ende bin...

Im Textfeld ist der letzte Wert jeder Zeile entweder "Ja" oder "Nein".
Zum Beispiel:

Code:
11245;Bezeichnung;111;222;333;Nein
11248;Kurzbezeichnung;333;66;99;Ja
11243;Bezeichnung ABC;1;2;3;Ja

Für die Datenbank muss ich das in "0" und "1" umwandeln. Das mache ich mit einer einfachen If-Abfrage.

PHP:
$trim = trim($_POST['werte']);
$zeilen = explode("\n", $trim);
 
foreach($zeilen as $zeile)
{
  $werte = explode(';', $zeile);
  
  if($werte[5] == 'Ja')
  { $neuer_wert = "1"; }
  elseif($werte[5] == 'Nein')
  { $neuer_wert = "0"; }
  
  $sql = "UPDATE tabelle SET feld2 = '$werte[2]', feld3 = '$werte[3]', feld4 = '$werte[4]', feld5 = '$neuer_wert' WHERE id = '$werte[0]'"; 
  $query = mysql_query($sql, $mysql) or die(mysql_error());
  
}

Das Problem ist, dass die 0/1 Umwandlung nur beim letzten Datensatz funktioniert, also bei der letzten Zeile, die im Textfeld eingegeben wurde. Bei den vorherigen Zeilen nicht. Ich habe mir den Wert $wert[5] ausgeben lassen - das stimmt noch, dort steht richtig entweder "Ja" oder "Nein". Wenn ich mir dann aber $neuer_wert ausgeben lasse, ist das bei allen Zeilen leer, außer eben bei der letzten. Wie oder wo kann das verloren gehen bzw. weshalb wird nur die letzte Zeile von der If Berücksichtigt?
 
Deine if-Abfrage sieht etwas seltsam aus. Probier es doch mal so:

PHP:
foreach($zeilen as $zeile)
{
  $werte = explode(';', $zeile);
  
  $neuer_wert = "0";
  if($werte[5] == 'Ja')
    $neuer_wert = "1";
  
  $sql = "UPDATE products SET feld2 = '$werte[2]', feld3 = '$werte[3]', feld4 = '$werte[4]', feld5 = '$neuer_wert' WHERE id = '$werte[0]'"; 
  $query = mysql_query($sql, $mysql) or die(mysql_error());
  
}
 
Leider klappt es auch damit nicht. Jetzt haben die Datensätze über der letzten Zeile zwar zwangsläufig auch einen Wert, nämlich 0, aber trotzdem reagiert nur die letzte Zeile auf die If...

Also wenn:

Ja
Ja
Nein
Ja
Ja

eingegeben wird, kommt trotzdem:

0
0
0
0
1

raus :/

Obwohl es so aussehen müsste:

1
1
0
1
1

EDIT: Ich habe wirklich keine Ahnung woran das liegt und würde das gerne verstehen. Also wenn jemand weiß, weshalb das mit der If nicht klappt, würde ich mich über diese Info sehr freuen.

Habe es nun anders gelöst und so funktionierts:

PHP:
foreach($zeilen as $zeile)
{
  $werte = explode(';', $zeile);
  
 $alter_wert = $werte[5];
 $neuer_wert = str_replace("Nein","0",$alter_wert);
 $neuer_wert = str_replace("Ja","1",$neuer_wert); 
  
  $sql = "UPDATE products SET feld2 = '$werte[2]', feld3 = '$werte[3]', feld4 = '$werte[4]', feld5 = '$neuer_wert' WHERE id = '$werte[0]'"; 
  $query = mysql_query($sql, $mysql) or die(mysql_error());
  
}
 
Zuletzt bearbeitet:
Zurück