each: FALSE auswerten
Chris Ross
- php
Hallo Forum,
warscheinlich hab ich ein dickes Brett vorm Kopf und seh den Wald vor lauter Bäumen nicht mehr. :/
"each()" gibt ja nach dem Ende des letzten Wertes "FALSE" zurück. Kann man dieses FLASE irgendwie auswerten, so a la
if(each == 'FALSE') { ... }
Ich brauche das für folgenden Hintergrund:
$termine ist ein mehrdimensionales Array, das mit Arrays gefüllt ist, dass die eigentlichen Werte enthält:
Array([0] => Array([t_kunde] => 2 [t_dienstl] => 3,19,12 [t_date] => 1126537000) [1] => Array([t_kunde] => 2 [t_dienstl] => 2,4 [t_date] => 1126517400 ))
foreach($termine as $t) {
$dienst = explode(",", $t['t_dienstl']);
while( list ($key, $val) = each($dienst)) {
$query = mysql_query("SELECT d_name FROM dienstleistung WHERE d_id = ".$val."");
// echo "key = ".print_r(each($dienst))."<br>";
$test = each ? 'true' : 'false';
if($test == 'false') {
$dienste .= mysql_result($query, 0, "d_name")."";
// echo "test";
}
else {
$dienste .= mysql_result($query, 0, "d_name")." / ";
}
}
$termin .= "</tr>\n<td class='td2' colspan='4'>".date("d.m.Y, G:i", $t['t_date'])." Uhr -> ".$dienste."</td>\n<tr>\n";
reset($dienst);
}
Das Problem ist jetzt, dass ich den String $dienste so formartieren will, das wenn die letzte Dienstleistung ausgegeben wird, diese OHNE den "Trennslash" dargestellt werden soll:
zeile 1: datum: dienstleistung3 / dienstleistung19 /dienstleistung12
zeile 2: datum: dienstleistung2 / dienstleistung4
Ich weiß nicht, ob ichs verständlich genug erklärt habe, was gefordert ist.
Für einen Tipp wäre ich wirklich sehr dankbar.
MfG
Chris
P.S. Das "$test = each ? 'true' : 'false';" oben im Code falsch ist, ist mir bekannt. Die auskommentierten Zeilen sind für mich zum debuggen und gehören nicht zum eigentlichen Code. ;)
echo $begrüßung;
Das Problem ist jetzt, dass ich den String $dienste so formartieren will, das wenn die letzte Dienstleistung ausgegeben wird, diese OHNE den "Trennslash" dargestellt werden soll:
zeile 1: datum: dienstleistung3 / dienstleistung19 /dienstleistung12
zeile 2: datum: dienstleistung2 / dienstleistung4
Sowas lässt sich mit einem Array, das man in deinem Fall mit ' / ' als "glue" implodieren lässt am elegantesten bewerkstelligen.
echo "$verabschiedung $name";
Moin!
warscheinlich hab ich ein dickes Brett vorm Kopf und seh den Wald vor lauter Bäumen nicht mehr. :/
Mutmaßlich. Ich denke aber, dein Problem liegt ganz woanders, als du es derzeit glaubst.
$termine ist ein mehrdimensionales Array, das mit Arrays gefüllt ist, dass die eigentlichen Werte enthält:
Array([0] => Array([t_kunde] => 2 [t_dienstl] => 3,19,12 [t_date] => 1126537000) [1] => Array([t_kunde] => 2 [t_dienstl] => 2,4 [t_date] => 1126517400 ))
Wo kommen diese Werte her? Doch wohl vermutlich aus einer Datenbankabfrage, die früher im Skript durchgeführt wurde. Warum machst du an dieser Stelle keinen JOIN der Dienstleistungs-ID auf den Dienstleistungsnamen? Weil deine Dienstleistungs-ID als kommaseparierte Liste und entgegen sämtlicher vernünftigerweise angwandten Normalisierungsregeln nicht als separate Tabelle angelegt ist - und das verursacht dir schon bei so einer simplen Aufgabe wie dem nachträglichen Zuordnen von ID zu Name Probleme.
foreach($termine as $t) {
$dienst = explode(",", $t['t_dienstl']);while( list ($key, $val) = each($dienst)) {
$query = mysql_query("SELECT d_name FROM dienstleistung WHERE d_id = ".$val."");
Außerdem feuerst du hier in schneller Abfolge für jede im Array enthaltene Dienstleistungs-ID einen kompletten SQL-Request auf die arme Datenbank. Wenn du schon von der nicht optimalen Datenstruktur der dem Array zugrundeliegenden Datenbank nicht wegkommen kannst, dann wäre zumindest an diesem Punkt doch noch heftiger Optimierungsbedarf, und zwar in den Stufen 1 (nur ein Request je Kunde) oder gar 2 (nur ein Request für das gesamte Array).
// echo "key = ".print_r(each($dienst))."<br>";
$test = each ? 'true' : 'false';
true und false sind keine Strings, also auch nicht in Anführungsstriche (egal ob doppelt oder einfach) zu setzen. Das nur so als Nebenbemerkung.
if($test == 'false') {
$dienste .= mysql_result($query, 0, "d_name")."";
// echo "test";
}
else {
$dienste .= mysql_result($query, 0, "d_name")." / ";
}
}$termin .= "</tr>\n<td class='td2' colspan='4'>".date("d.m.Y, G:i", $t['t_date'])." Uhr -> ".$dienste."</td>\n<tr>\n";
reset($dienst);
}
Insgesamt hat dein Codeausschnit eine große Ansammlung von eher suboptimalen Konstruktionen, die die Bewältigung der Aufgabe ziemlich aufwendig machen.
Um mal ein paar alternative Lösungsansätze zusammenzufassen:
1. Die Möglichkeit, schon direkt beim ursprünglichen Query auch den bzw. die Dienstleistungsnamen mit abzufragen, hatte ich oben erwähnt.
2. Wenn das Abfragen der zur ID zugehörigen Dienstleistungsbezeichnung ein häufigerer Vorgang ist, sollte er unbedingt in einer Funktion ausgelagert werden. Das entzerrt einerseits den hier sich offenbarenden Quelltext-Wühlkram, und es trennt auch die Aufgabenbereiche: Innerhalb der Funktion beschäftigt man sich ausschließlich mit der Wandlung der ID in eine Bezeichnung, außerhalb der Funktion ist ausschließlich die Ausgabe der DB-Informationen wichtig.
Das Problem ist jetzt, dass ich den String $dienste so formartieren will, das wenn die letzte Dienstleistung ausgegeben wird, diese OHNE den "Trennslash" dargestellt werden soll.
Dein Programmansatz kann gar nicht funktionieren, weil du die while-Schleife dort installiert hast. Das Innere der while-Schleife wird ausgeführt, wenn der in runden Klammern stehende Ausdruck etwas ergibt, was PHP als true betrachtet. Kommt hingegen etwas heraus, was PHP als false betrachtet, wird die Schleife sofort verlassen, und danach weitergemacht. Mit anderen Worten: Innerhalb der Schleife ist es total sinnlos, abfragen zu wollen, ob dein each false ergeben hat, denn wenn das der Fall wäre, würde die Schleife ja nicht mehr durchlaufen und diese Abfrage nie erreicht werden.
Wie dedlfix schon sagte: implode() ist eine schöne Funktion, welche ein Array mit einem definierbaren String zusammensetzt. Hättest du also ein Array
$dienste = array("Dienst 1", "Dienst 2", "Dienst 23");
würdest du mit
echo implode(" / ",$dienste);
dann die Liste, schön getrennt mit dazwischenliegenden Schrägstrichen, erhalten.
- Sven Rautenberg
Moin Moin,
Wo kommen diese Werte her? Doch wohl vermutlich aus einer Datenbankabfrage, die früher im Skript durchgeführt wurde. Warum machst du an dieser Stelle keinen JOIN der Dienstleistungs-ID auf den Dienstleistungsnamen? Weil deine Dienstleistungs-ID als kommaseparierte Liste und entgegen sämtlicher vernünftigerweise angwandten Normalisierungsregeln nicht als separate Tabelle angelegt ist - und das verursacht dir schon bei so einer simplen Aufgabe wie dem nachträglichen Zuordnen von ID zu Name Probleme.
Jede Medaille hat 2 Seiten: Mein Lösungsansatz für das Projekt sind 3 Tabellen:
1. Dienstleistungen -> mit d_id, d_nummer, d_name, sowie d_date wann angelegt
2. kunden -> mit k_id, k_name, k_vorname ... usw usw
3. termine -> mit t_id, t_k_id, t_d_id, sowie date ..
Jeder Kunde kann mehrere Termine mit unterschiedlichen Dienstleistungen haben. Diese Tabelle vergrößert sich also ständig, wobei sich Kunden viel weniger und Dienstleistungen fast gar nicht vergrößert. Um nicht jedemenge ellenlange Strings in der Tabelle Termine zu haben, trage ich dort also für jeden Termin lediglich die Kunden-ID, sowie die Dienstleistungs-ID's als String und das Datum ein. Das spart erheblich Platz, weil viel weniger Daten gspeichert werden müssen.
Ich habe das jetzt wie folgt gelöst:
function xyz($k_id) {
$query = "SELECT * FROM termine WHERE t_kunde = $k_id ORDER BY t_date ASC";
$num = mysql_num_rows($sql);
for($i=0; $i<$num; $i++) {
$daten = mysql_fetch_row($sql);
$row = explode(",", $daten[2]);
unset($data_dienst);
foreach($row as $r) {
$q1 = mysql_query("SELECT d_name FROM dienstleistung WHERE d_id = $r");
$data_dienst[] = mysql_result($q1, 0, "d_name");
}
$data_termine[] = array("t_id" => $daten[0], "t_kunde" => $daten[1], "t_dienstl" => implode(" / ", $data_dienst), "t_date" => $daten[3]);
}
unset($k_id);
return $data_termine;
}
Damit klappt es ganz gut. Dass das nicht der Weiheit letzter Schluss ist, darüber bin ich mir auch im klaren. :)
Danke für die Tipps.
MfG
Chris