Frmulardaten lassen sich nicht ändern
detlevk
- php
Und wieder einmal muss ich euch mit einem Anfängerproblem belästigen. Ich hoffe, dass meine Darstellung einigermaßen übersichtlich ist, wenn auch leider etwas lang (wg. vollständigem Code):
Kurzbeschreibung des Projekts Es soll ein Shop mit PHP und MySQL erstellt werden. In diesem Shop gibt es einen Warenkorb. Dieser ist als assoziatives Array angelegt, das in der Session registriert wird. Die Anzeigeseite eines bestimmten Artikels enthält diese Buttonleiste:
Von der Anzeigeseite eines bestimmten Artikels soll dieser durch Klick auf das Symbol dem Warenkorb hinzugefügt werden. Das Symbol dient der Ansicht des derzeitigen Bestandes im Warenkorb ohne etwas zu verändern. Die Ansicht des Warenkorbes soll nach Hinzufügen eines Artikels z.B. so aussehen: Durch den grünen Button soll die Anzahl je Klick um 1 erhöht werden, der rote Button vermindert um 1. Das Mülltonnensymbol löscht den Artikel komplett aus dem Warenkorb. Der Button mit dem durchgestrichenen Warenkorbsymbol löscht den kompletten Warenkorb. Durch Klick auf den Button „Bestellung“ kommt man zu einer Eingabemaske für die notwendigen Daten: Die roten Sterne markieren die verpflichtenden Eingaben. Ebenfalls verpflichtend ist die Checkbox zur Kenntnisnahme der AGB.
Code des Formulars: (Ausschnitt aus Maske.php)
<form method="post" action="Checkout.php" name="Bestellung">
<table style="background-color: rgb(204, 204, 204);
width: 534px; height: 366px;
text-align: left; margin-left: auto; margin-right: auto;"
border="0" cellpadding="2" cellspacing="2">
<tbody><tr><td style="text-align: left; background-color: rgb(204, 204, 204);">Anrede:</td>
<td style="text-align: left;">
<select name="anrede">
<option>Frau</option>
<option>Herr</option></select></td></tr>
<tr><td style="text-align: left;">Vorname:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="vorname"></td></tr>
<tr><td style="text-align: left;">Name:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="nachname"></td></tr>
<tr><td style="text-align: left;">Anschrift:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="anschrift"></td></tr>
<tr><td style="text-align: left;">PLZ:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="12" size="12" name="plz"></td></tr>
<tr><td style="text-align: left;">Ort:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="ort"></td></tr>
<tr><td style="text-align: left;">Land:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;">
<select name="land">
<option>Deutschland</option>
<option>Österreich</option>
<option>Schweiz</option>
<option>Niederlande</option>
<option>Belgien</option>
<option>Luxemburg</option></select></td></tr>
<tr><td style="text-align: left;">Telefon:</td>
<td style="text-align: left;"><input name="tel"></td></tr>
<tr><td style="text-align: left;">Email:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="email"></td></tr>
<tr><td>Nachricht:</td><td><textarea cols="50" rows="5" name="textfeld"></textarea></td></tr>
<tr><td style="text-align: right;"><input name="agb" type="checkbox"></td>
<td>Die <a href="AGB.html">allgemeinen Geschäftsbedingungen</a>
habe ich zur Kenntnis genommen.</td></tr><tr><td></td>
<td style="text-align: center;">
<input value="Abschicken" type="submit">
<input value="Löschen" type="reset"></td></tr>
</tbody></table>
</form>
Nach dem Abschicken erscheint eine Übersicht, bei der sowohl die erfassten Lieferdaten als auch die Bestellliste angezeigt werden:
Die Lieferdaten werden von diesem Skript (Checkout.php) aus dem Webformular entnommen, ausgewertet und ebenfalls in der Session registriert. Der obere graue Ändern-Button ruft die Maske (Maske.php) wieder auf, um die Daten dort neu einzugeben. Der untere, noch weiße Ändern-Button ruft den Warenkorb wieder auf (Liste.php), um dort Änderungen vorzunehmen.
Code Checkout.php:
<?php
session_start();
$_SESSION['anrede'] = $anrede;
$_SESSION['vorname'] = $vorname;
$_SESSION['nachname'] = $nachname;
$_SESSION['anschrift'] = $anschrift;
$_SESSION['plz'] = $plz;
$_SESSION['ort'] = $ort;
$_SESSION['land'] = $land;
$_SESSION['tel'] = $tel;
$_SESSION['email'] = $email;
$_SESSION['textfeld'] = $textfeld;
$_SESSION['agb'] = $agb;
function fehler()
{
?>
<h1 align=center>Unvollständige Eingabe!</h1><br>
<p align=center><a href="javascript:history.back();">Zurück</a></p>
<?php
}
function versand_berechnen($land, $paket, $reg)
{
if ($land == "Deutschland")
{
if ($paket)
{
$versand = 5; //Versand als Paket
}
else
{
$versand = 2.5; //Versand als Brief
}
}
else if ($land == "Schweiz")
{
if ($paket)
{
$versand = 30; //Versand als Paket außerhalb EU
}
else if ($reg)
{
$versand = 8; //Versand als Einschreiben
}
else
{
$versand = 5; //Versand als Brief
}
}
else
{
if ($paket)
{
$versand = 17; //Versand als Paket in EU
}
else if ($reg)
{
$versand = 8; //Versand als Einschreiben
}
else
{
$versand = 5; //Versand als Brief
}
}
return $versand;
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1250">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title>Zusammenfassung</title>
</head>
<body>
<?php
if (empty($vorname) || empty($nachname) || empty($anschrift) || empty($plz)
|| empty($ort) || empty($email) || empty($agb))
{
fehler();
}
else
{
$erfasst = 1; //Daten erfolgreich erfasst
$_SESSION['erfasst'] = $erfasst;
?>
<p align=center><img alt='Logo' src='../Logos/Logo_lang.gif'></p>
<h1 align=center>Zusammenfassung:</h1>
<?php
if ($textfeld)
{
$width = 600;
}
else
{
$width = 300;
}
?>
<table align=center width=<?=$width?>>
<tr><td valign=top><h2>Lieferanschrift:</h2></td>
<?php
if ($textfeld)
{
echo "<td valign=top><h2>Ihre Nachricht:</h2></tr>";
}
else
{
echo "</tr>";
}
echo "<tr><td>$vorname $nachname<br>$anschrift<br>";
echo "$plz $ort<br>$land<br>";
echo "$tel</td>";
if ($textfeld)
{
echo "<td width=50% valign=top>$textfeld</td></tr>";
}
else
{
echo "</tr>";
}
?>
</table>
<p align=center><a href="Maske.php">
<img alt="Ändern" src="../Buttons/Aendern_grau.gif" border=0></a></p>
<h2 align=center>Ihre Bestellung:</h2>
<table align=center><tr><th></th><th>BestNr</th><th>Bezeichnung</th>
<th>Anzahl</th><th>Preis</th><th>Gesamtpreis</th>
<?php
//Ausgabe der Artikelliste
$zaehler = 1;
foreach ($korb as $key => $wert)
{
$zwisu = sprintf("€%7.2f ", $wert[1] * $wert[2]);
$zeile = "<tr><td>$zaehler.</td><td>$key</td>";
$zeile .= "<td>$wert[0]</td><td align=right>$wert[1]</td><td>€ $wert[2]</td>
<td align=right>$zwisu</td></tr>";
echo $zeile;
$sumItem = $sumItem + $wert[1]; //Gesamtzahl aufsummieren
$sumPrice = $sumPrice + ($wert[1] * $wert[2]); //Gesamtpreis aufsummieren
$sumZeile = "<tr><td></td><td></td><td><b>Zwischensumme:</b></td>
<td align=right><b>$sumItem</b></td>";
$sumZeile .= "<td></td><td align=right>
<b>€ ".number_format($sumPrice, 2, ',', '.')."</b></td></tr>";
$zaehler++;
if ($land == "Deutschland" && $wert[3] == 5 || $sumPrice > 40)
{
$paket = 1; //Flag für Versand als Paket
}
else if ($land != "Deutschland" && $wert[4] == 8 || $sumPrice > 20)
{
$reg = 1; //Flag für Versand als Einschreiben
}
}
echo $sumZeile;
$versand = versand_berechnen($land, $paket, $reg);
$versand = number_format($versand, 2, ',', '.');
echo "<tr><td></td><td></td><td>Versand:</td><td></td><td></td>
<td align=right>€ $versand</td></tr>";
$gesamt = $sumPrice + $versand;
$gesamt = "€ ".number_format($gesamt, 2, ',', '.');
echo "<tr><td></td><td></td><td><b>Gesamtsumme:</b></td><td></td><td></td>
<td align=right><b>$gesamt</b></td></tr></table>";
?>
<p align=center>
<a href="Liste.php">
<img alt="Ändern" src="../Buttons/Aendern.gif" border=0></a>
<a href ="Erfassung.php">
<img alt="Abschließen" src="../Buttons/Abschliessen.gif" border=0></a>
</p>
<?php
}
?>
</body>
</html>
Problem: Der Warenkorb kann beliebig geändert werden. Die Lieferdaten oben aber können, wenn sie registriert sind, nicht mehr geändert werden! Ohne Registrierung gehen sie aber im Falle einer Änderung des Warenkorbs verloren. Unverständlich: Der Warenkorb ist auch in der Session registriert und wird durch die Änderungen nach Belieben überschrieben. Warum werden die Formulardaten nicht mehr überschrieben?
Hello,
ich bin mir nicht sicher, welche Funktion Du genau vermisst, aber warum lässt Du in der Maske nicht die in der Session enthaltenen Daten anzeigen?
<input maxlength="50"
size="50"
name="vorname"
value="<?php echo (isset($_SESSION['vorname']))?htmlspecialchars($_SESSION['vorname']):'';?>" />
usw.
für die anderen <input>-Elemente
<tr><td style="text-align: left;">Name:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="nachname"></td></tr>
<tr><td style="text-align: left;">Anschrift:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="anschrift"></td></tr>
<tr><td style="text-align: left;">PLZ:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="12" size="12" name="plz"></td></tr>
<tr><td style="text-align: left;">Ort:<span style="color: rgb(255, 0, 0);">*</span></td>
<td style="text-align: left;"><input maxlength="50" size="50" name="ort"></td></tr>
<tr><td style="text-align: left;">Land:<span style="color: rgb(255, 0, 0);">*</span></td>
Liebe Grüße aus Syburg
Tom vom Berg
Hello,
ich bin mir nicht sicher, welche Funktion Du genau vermisst, aber warum lässt Du in der Maske nicht die in der Session enthaltenen Daten anzeigen?
Hatte ich auch schon versucht.
Das ändert aber nichts daran, dass die dort eingegebenen Daten, einmal registriert, nicht mehr änderbar sind!
Ohne die Anzeige der Daten erscheint die Maske leer. Wenn dann dort Daten eingegeben werden, werden diese komplett ignoriert und Checkout zeigt die vorher eingegebenen Daten.
Das gleiche passiert natürlich, wenn man die vorherigen Daten in der Maske anzeigt und ändert.
Vermisst wird übrigens die Möglichkeit, dass der Benutzer die in der Maske eingegebenen Daten über Checkout kontrollieren und ggf. ändern kann.
Hello,
[code lang=html]<form method="post" action="Checkout.php" name="Bestellung">
ist das der vollständige Code von Checkout?
Code Checkout.php:
[code lang=php]<?php
session_start();
$_SESSION['anrede'] = $anrede;
$_SESSION['vorname'] = $vorname;
$_SESSION['nachname'] = $nachname;
$_SESSION['anschrift'] = $anschrift;
$_SESSION['plz'] = $plz;
$_SESSION['ort'] = $ort;
$_SESSION['land'] = $land;
$_SESSION['tel'] = $tel;
$_SESSION['email'] = $email;
$_SESSION['textfeld'] = $textfeld;
$_SESSION['agb'] = $agb;
Wie sind Deine Einstellungen für
register_globals
magic_quotes_gpc
?
Hast Du Dir (zum Debuggen) schon mal die Daten aus dem Formular anzeigen lassen, bevor Du sie in die Session schreibst?
Liebe Grüße aus Syburg
Tom vom Berg
Wie sind Deine Einstellungen für
register_globals
magic_quotes_gpc
Der Code für Checkout.php ist vollständig wiedergegeben.
register_globals ist on.
magic_quotes_gpc ist off.
Übrigens: Den letzteren kenne ich noch nicht. Was bedeutet der?
?
Hast Du Dir (zum Debuggen) schon mal die Daten aus dem Formular anzeigen lassen, bevor Du sie in die Session schreibst?
Ja habe ich. Ohne Session-Registrierung lassen die sich auch beliebig ändern. Das nützt mir nur nichts, da ich sie nicht verlieren will, wenn der User seinen Warenkorb ändert.
Hello,
Wie sind Deine Einstellungen für
register_globals
magic_quotes_gpcDer Code für Checkout.php ist vollständig wiedergegeben.
register_globals ist on.
Das ist eine ganz schlechte Idee
magic_quotes_gpc ist off.
Das hingegen erspart einiges an Arbeit, darf aber nicht vergessen werden!
Übrigens: Den letzteren kenne ich noch nicht. Was bedeutet der?
Schau mal unter http://www.php.net/manual/en/info.configuration.php#ini.magic-quotes-gpc
Wann startest Du denn Deine Session immer?
Du solltest das Ganze erst einmal auf einen neueren Standard heben. Schalte auch register_globals und register_long_arrays ab. Und dann arbeite mit den "superglobalen" Arrays $_GET, $_POST, $_SESSION, ...
Dann teile Deinen ganzen Apparat in einzelne Formulare auf.
Ordne sie in eine Hierarchie ein.
Ordne die Daten in dr Session auch etwas stricter, also lege nicht alle Datenfelder gleich direkt unter $_SESSION an, sondern passend zum Vorgangsstatus und/oder dem zugehörigen Formular
$_SESSION['adresse']['vorname']
$_SESSION['adresse']['name']
$_Session['warenkorb']['produkte'][1]
$_Session['warenkorb']['produkte'][2]
$_Session['warenkorb']['produkte'][3]
oder so ähnlich.
Ordne jedem Formular seine eigene Anzeige- und seine eigene Auswertefunktion zu. Die kann man auch in einer verpacken, wenn man das unbedingt will. In der Anzeigefunktion werden dann die Buttons (Submits) deklariert, die die Ablaufsteuerung der Auswertefunktion wieder aufnimmt.
So solltest Du dann langsam Ordnung in Dein Projekt bekommen...
Liebe Grüße aus Syburg
Tom vom Berg
Hello,
»» > Wie sind Deine Einstellungen für
»» > register_globals
»» > magic_quotes_gpc
»»
»» Der Code für Checkout.php ist vollständig wiedergegeben.
»»
»» register_globals ist on.Das ist eine ganz schlechte Idee
»» magic_quotes_gpc ist off.
Das hingegen erspart einiges an Arbeit, darf aber nicht vergessen werden!
Die Einstellungen der php.ini sind vom Provider vorgegeben.
Wann startest Du denn Deine Session immer?
session_start() steht in der Regel immer am Anfang.
Ansonsten weiß ich selbst, dass mein Code nicht optimal organisiert ist. Teilweise fehlt mir der theoretische Hintergrund. Ein Informatikstudium kann ich schlecht nebenher in ein paar Tagen absolvieren.
Und ich bin nun einmal kein Informatiker, sondern nur Datenverarbeitungskaufmann, der sich PHP in kompletter Eigenregie beibiegt!
Und von daher interessiert hauptsächlich das aktuelle Problem:
Warum können vom Formular übergebene Daten nach Registrierung in der Session nicht mehr bearbeitet werden?
Auch wenn ich das Formular scheinbar leer abschicke, sind die Daten doch irgendwo unsichtbar noch vorhanden!
Problem:
Der Warenkorb kann beliebig geändert werden. Die Lieferdaten oben aber können, wenn sie registriert sind, nicht mehr geändert werden! Ohne Registrierung gehen sie aber im Falle einer Änderung des Warenkorbs verloren.
Unverständlich:
Der Warenkorb ist auch in der Session registriert und wird durch die Änderungen nach Belieben überschrieben. Warum werden die Formulardaten nicht mehr überschrieben?
Beobachtung hierzu:
$_SESSION scheint Vorrang vor $_POST zu haben.
Wenn $_SESSION['variable'] existiert, wird $_POST['variable'] ignoriert.
$variable wird im Programm also immer den Wert von $_SESSION haben.
Ich vermute mal, das liegt an register_globals = on in der PHP.INI.
Die ist leider vom Provider so vorgegeben.
Hello,
Beobachtung hierzu:
$_SESSION scheint Vorrang vor $_POST zu haben.
Nein, aber du liegst schon fast richtig:
Wenn $_SESSION['variable'] existiert, wird eine Scriptvariable mit dem Namen $variable angelegt.
$_POST bleibt davon unebrührt.
Deshalb hatte ich Dir ja gesagt, du sollst $_POST nehmen.
$variable wird im Programm also immer den Wert von $_SESSION haben.
$variable kommt aus $_SESSION, wenn die Reihenfolge entsprechend eingestellt ist (EGPCS)
http://www.php.net/manual/en/ini.core.php#ini.register-globals, weil immer das letzte die vorigen überschreibt...
Ich vermute mal, das liegt an register_globals = on in der PHP.INI.
Ja.
Aber die solltest Du ggf. auch in einer .htaccess-Datei ausschalten können.
Läuft PHP bei Dir als Modul oder als CGI?
Darüber gibt die die PHP-Information Auskunft (phpinfo())
Liebe Grüße aus Syburg
Tom vom Berg
echo $begrüßung;
» $variable wird im Programm also immer den Wert von $_SESSION haben.
$variable kommt aus $_SESSION, wenn die Reihenfolge entsprechend eingestellt ist (EGPCS)
http://www.php.net/manual/en/ini.core.php#ini.register-globals, weil immer das letzte die vorigen überschreibt...
Das S steht hier aber für SERVER. Dass die Session die bereits vorhandenen Variablen überschreibt liegt daran, dass die Variablen aus EGPCS vor dem Scriptstart angelegt werden, die aus der Session aber erst mit session_start() hinzukommen.
» Ich vermute mal, das liegt an register_globals = on in der PHP.INI.
Dass register_globals angeschaltet ist, ist kein Grund, auf dieses Feature zu bauen. Zusammen mit schlechter Programmierung ist das Feature eine Sicherheitslücke und deshalb schon seit vielen Versionen per Default ausgeschaltet (nur einige Provider wollen sich Kundensupport ersparen - zum Preis von möglichen Sicherheitslücken) und wird mit PHP 6 ersatzlos gestrichen. Zusätzlich zum generellen Verwenden der $_*-Arrays ist anzuraten, penibel vor jedem Verwenden einer Variable, sie mit einem Default-Wert zu initialisieren. Das muss so programmiert sein, dass auch bei Verzweigungen stets eine Initialisierung erfolgt.
if (!Test)
$errors[] = "ein Fehler";
else
...
foreach ($errors as ...)
In diesem Beispiel gibt es $errors nicht, wenn der Test erfolgreich war. Das anschließende foreach greift im besten Fall ins Leere, im schlechten Fall auf irgendwas vorhandenes. Ein
$errors = array();
vor dem if sorgt für eine garantierte Existenz. Und auch wenn durch register_globals=on über welchen unerwünschten Weg auch immer $errors angelegt wurde, ist es mit der expliziten Initialisierung unschädlich gemacht worden.
echo "$verabschiedung $name";