E-COMMERCE Listings auf Heft-CD > neu angelegten Datenbank iproshop und über den Button Durchsuchen … zur genannten SQL-Datei. Nach dem Klick auf OK wird die Tabelle angelegt. Für die Warenkorbfunktion kommt eine zweite Tabelle zum Einsatz: UID varchar(32) NOT NULL, PID varchar(4) NOT NULL, ANZ smallint(6) DEFAULT '0' NOT NULL, DATUMZEIT datetime NOT NULL default '0000-00-00 00:00:00' Gespeichert werden eine eindeutige User-ID (UID), die zum gewählten Produkt gehörende ID (PID) sowie die gewünschte Anzahl (ANZ). Zusätzlich wird noch das Feld DATUMZEIT mit dem aktuellen Zeitstempel belegt, um den Warenkorb später »aufräumen« zu können. ■ Nutzeridentifikation Zur Ausführung der Anwendung im Multi-User-Betrieb benötigen alle Teilnehmer eine eindeutige Kennung. Dazu wird beim Aufrufen der Startseite von PHP eine Session-ID generiert, die gemeinsam mit der User-ID und den Bestelldaten der Warenkorbtabelle vermerkt wird und an alle weiteren PHPSkripts übergeben wird. Somit beziehen Mini-Shopping Module von IPro-Shop bestellung.php Bestellung vorbereiten (Kundendaten eingeben, Formular absenden) Shop-Anwendungen werden auch für kleinere Websites zunehmend interessanter. Internet Pro zeigt, wie Sie mit PHP und einer MySQLDatenbank eine einfache, ausbaufähige Applikation erstellen. db.php VO N T H O M A S M E I N I K E index.php ■ Ein Webserver mit Datenbank-Anbindung kann dem Experimentieren mit ausschließlich auf Javascript basierenden Warenkörben ein Ende setzen. Wir stellen eine mit der Skriptsprache PHP 4 entwickelte Anwendung vor, bei der zur Datenhaltung die Datenbank MySQL verwendet wird – womit die technischen Voraussetzungen feststehen. Die Hauptkomponenten sind die Module Katalog, Warenkorb und Bestellung, und sie werden auch in dieser Reihenfolge aufgerufen. Den eigentlichen Katalog bildet die Datenbanktabelle katalog mit folgender Struktur: ■ Aufbau und Struktur PREIS decimal(4,2) DEFAULT '0.00' Das Beispiel »IPro-Shop« besteht aus mehreren PHP-Modulen und der MySQL-Datenbank iproshop. Zum Anlegen und Pflegen der Datenbank empfiehlt sich das unter der Adresse phpmyadmin.source forge.net verfügbare Tool phpMyAdmin. Die Abbildung »Schnell erstellt« veranschaulicht die notwendigen Schritte zur Administration. Geben Sie iproshop unter Neue Datenbank erzeugen ein und klicken Sie auf den Erzeugen-Button. 84 INTERNET PROFESSIONELL ■ APRIL 2002 PID varchar(4) NOT NULL, Modul für die Datenbankzugriffe indenkorb.php Produkte in den Warenkorb legen Startseite (löscht Warenkorbeinträge, die älter als 24 Stunden sind) iproshop.css externes Stylesheet iproshop.js externe Datei mit Javascript-Funktionen katalog.php Produktkatalog anzeigen PNAME varchar(50) NOT NULL, katalog.sql PINFO text NOT NULL, SQL-Datei zum Erstellen der Tabelle katalog in der Datenbank iproshop NOT NULL, korbleeren.php PRIMARY KEY (PID), nach Bestellung Warenkorb löschen UNIQUE PID (PID) korbupdate.php Darin werden pro Produkt eine ProduktID (PID), ein Name (PNAME), eine Beschreibung (PINFO) und ein maximal vierstelliger Preis mit zwei Nachkommastellen abgelegt. In der Datei katalog.sql stehen die Tabellenstruktur und zehn Produktvorgaben zum Import bereit. Wechseln Sie dazu in phpMyAdmin zur Änderungen des Warenkorbinhalts losgehts.php E-Mail mit den Bestellinformationen warenkorb.php aktuellen Warenkorbinhalt anzeigen warenkorb.sql SQL-Datei zum Erstellen der Tabelle warenkorb in der Datenbank iproshop ILLUSTRATION: CHRISTINA STEINER WARENKORB MIT PHP UND MYSQL PROGRAMMIEREN E-COMMERCE Shop-Anwendung selbst gemacht Schnell erstellt: Alle Sessions und Mail mit PHP unter Windows Schritte zum Erstellen der Datenbank und der Tabellen mit php My Admin auf einen Blick. Bei Hosting-Providern dürfte es kaum Probleme mit diesen Optionen geben, da sie meist lauffähig vorkonfiguriert sind. Falls Sie unter Windows mit PHP entwickeln, passen Sie die Datei php.ini folgendermaßen an: Im Abschnitt [Session] wird der Pfad zum temporären Speichern der Session-Daten benötigt, zum Beispiel session.save_path = C:\Apache\htdocs\ sessions\temp. Zum Mail-Versand ist im Abschnitt [mail function] der Name des vom lokalen Rechner aus erreichbaren SMTP-Servers anzugeben, etwa SMTP = smtpserver.provider.de. Starten Sie nach den Änderungen den Webserver neu. sich alle Handlungen auf den persönlichen Warenkorb. Die Session wird mit diesem Code erzeugt und weitergeführt: Übersicht: Die Katalogansicht wird aus dem Inhalt der Datenbanktabelle »katalog« erzeugt. ausgewertet. Dabei wird folgende SQLAbfrage wirksam: INSERT INTO warenkorb <?php (UID,PID,ANZ,DATUMZEIT) VALUES session_start(); ('$PHPSESSID','$PID',$ANZ,now()) ?> Intern steht die Umgebungsvariable $PHPSESSID zur Verfügung, die an alle Links in der Form Falls es zu diesem Produkt bereits einen Eintrag gibt, wäre es unpraktisch, einen weiteren zu erzeugen. In diesem Fall wird der bestehende Datensatz ergänzt: <a href="datei.php?ID=<?= UPDATE warenkorb SET ANZ=ANZ+$ANZ $PHPSESSID;?>">Linktext</a> angehängt wird. Am Anfang jeder weiteren Skriptdatei erfolgt die Prüfung der Session-ID auf Existenz. Ist die Session abgelaufen oder nicht verfügbar, wird auf die Startseite verwiesen und eine neue Session erzeugt. session_start(); if($ID!=$PHPSESSID) { session_destroy(); Header("Location: index.php"); exit(); } Dabei handelt es sich um eine zufällig generierte 128-Bit-Prüfsumme in hexadezimaler Notation mit 32 Zeichen, wie 07651c77a6d2e49f96159c4f 791ea900. WHERE PID='$PID' AND UID='$PHPSESSID' Die Verknüpfung der Formulardaten mit PHP und MySQL-Abfragen finden Sie im »Listing 1«. Die Variablen $test1 beziehungsweise $test2 dienen im weiteren Ablauf als Prüfkriterium, ob die Daten in den Warenkorb übernommen worden sind oder nicht. Für den Benutzer besteht an diesem Punkt die Möglichkeit, den Warenkorb in Ruhe einzusehen, zu ergänzen oder teilweise zu löschen. Dazu dient das hinter dem Button Warenkorb aktualisieren liegenden Skript korbupdate.php mit den SQL-Anweisungen: korb abgelegten Informationen mit SELECT * FROM warenkorb WHERE UID='$PHPSESSID' ORDER BY PID ausgelesen und mit den Preisen aus der Datenbanktabelle katalog verknüpft: SELECT PNAME AS name, PREIS*$zeile[ANZ] AS teilsumme FROM katalog WHERE PID='$zeile[PID]' Daraus entsteht die Auflistung der Produkte, deren gewünschter Anzahl, Listing 1 while(list($PID,$ANZ)= each($HTTP_POST_VARS)) { if($ANZ) { $test1++; $abfrage="SELECT COUNT(PID) FROM warenkorb WHERE PID= '$PID' AND UID='$PHPSESSID'"; $ergebnis=mysql_query($abfrage, $dbref); if(mysql_result($ergebnis,0,0)==1) UPDATE warenkorb SET ANZ=$ANZ WHERE { PID='$PID' AND UID='$PHPSESSID' $abfrage="UPDATE warenkorb SET DELETE FROM warenkorb WHERE ■ Vom Katalog in den Warenkorb Wird der Katalog-Link aktiviert, erscheint eine Tabelle mit den aktuellen Produktinformationen und zugeordneten Eingabefeldern für die jeweilige Anzahl. Hier werden nur positive ganze Zahlen akzeptiert – zur Prüfung auf gültige Eingaben dient eine Javascript-Funktion, die im Textkasten auf der nächsten Seite näher beschrieben ist. Die Auswahl wird durch Klicken auf den Button In den Warenkorb legen abgeschlossen. Im Skript indenkorb.php wird das übergebene Array $HTTP_POST_VARS in einer while()-Schleife ANZ=ANZ+$ANZ WHERE PID='$PID' PID='$PID' AND UID='$PHPSESSID' AND UID='$PHPSESSID'"; } ■ Der Bestellvorgang Die eigentliche Bestellung ausgehend von bestellung.php erfolgt im Beispiel über eine generierte E-Mail, nachdem der Kunde seine persönlichen Daten wie Name, Postanschrift, E-Mail-Adresse sowie optional Kunden- und Telefonnummer in ein Formular eingetragen und die Bestellung bestätigt hat. Die Konsistenz der in die Pflichtfelder eingegebenen Daten prüft wiederum eine JavascriptFunktion. Zuvor werden die im Waren- else { $abfrage="INSERT INTO warenkorb (UID,PID,ANZ,DATUMZEIT) VALUES ('$PHPSESSID','$PID',$ANZ, now())"; } $ergebnis=mysql_query($abfrage, $dbref); $test2+=$ergebnis; } } INTERNET PROFESSIONELL ■ APRIL 2002 85 E-COMMERCE Shop-Anwendung selbst gemacht Alles eingekauft? Im Warenkorb liegen die gewählten Produkte, wobei Änderungen noch möglich sind. Bestellungen durchführen. Beim Verwerfen der aktuellen Bestellung wird über korbleeren.php auch der Warenkorb gelöscht, nicht jedoch die Session. ■ Aufräumen und Ausblick Bei der realisierten Anwendung sammelt sich mit der Zeit in der Datenbanktabelle warenkorb Datenmüll von bereits abgelaufenen Sessions an. Um diesen einzudämmen, wird bei jedem Neustart im Skript index.php das Löschen aller Warenkorbinhalte mit einem Zeitstempel größer 24 Stunden initiiert: DELETE FROM warenkorb WHERE UNIX_TIMESTAMP(now())-UNIX_TIMESTAMP (DATUMZEIT)>86400 Kaufen: Ansicht der zu bestellenden Produkte mit Preisen und Gesamtsumme. Nach dem Eintragen der Kundendaten kann die Bestellung ausgelöst werden. der Preise sowie der zu zahlenden Gesamtsumme. Ein Klick auf den Button Bestellung absenden aktiviert das Skript losgehts.php. Im Hintergrund wird die E-Mail versandfertig gemacht und mit der PHP-Funktion mail($an,$betreff,$text, $optional); auf den Weg zum Shop-Inhaber gebracht und als Kopie an den Besteller übermittelt. Letzterer sieht als Ergebnis eine Auftragsbestätigung im Browser. Dort werden noch einmal alle Daten in einer Übersicht zusammengefasst. Der Warenkorb ist zu diesem Zeitpunkt bereits mit der Funktion DELETE FROM warenkorb WHERE UID='$PHPSESSID' geleert und die Session auf dem Server mit der PHP-Funktion session_destroy() beendet. Da die Session-ID im Browser bis zum Schließen des Browsers weiterhin existiert, könnte der Kunde noch weitere Das funktioniert auch unter Windows problemlos. Ein anderer Ansatz wäre ein Link zum Abmelden aus der Anwendung mit Löschung des Warenkorbs sowie Außerkraftsetzung der Session, wie es bei Freemail-Diensten praktiziert wird. Weitere denkbare Verbesserungen sind Kundennummern zur Registrierung von Kundenprofilen, zusätzliche Eingabefelder für Bankinformationen, erweiterte Produktkategorien in Form von Auswahllisten und zusätzliche Tabellen für Lagerhaltung und Abrechnung – genug Raum also für eigene Ideen. Zum Live-Test steht die Anwendung unter www.datenverdrah ten.de/ iproshop bereit. [AWE] Bestellung kann nicht erfolgen'); Javascript-Funktionen test2=false; Javascript ist zur kompletten Realisierung von Warenkorb-Anwendungen eher ungeeignet. Sinnvoll ist die Verwendung von Prüfroutinen für Browser. Fehler in Formularen lassen sich vor Absenden an den Server erkennen und vermeiden. } Zusätzliche Server-seitige Prüfungen müssen vorgesehen werden, da Javascript deaktiviert sein kann. Das Katalogdokument enthält die Javascript-Funktion FormularCheck_Katalog(), die mit einer For-Schleife leere oder mit anderen als numerischen Inhalten belegte Eingabefelder aufspürt. Nach dem Anzeigen eines Hinweises wird der Eingabefokus auf das beanstandete Feld gesetzt. { function FormularCheck_Katalog() { FormularCheck_Bestellung(summe) zuständig. Geprüft wird, ob die Pflichtfelder ausgefüllt sind, die Postleitzahl vom Typ Number ist und fünf Stellen besitzt sowie die E-MailAdresse, die mindestens ein @-Zeichen und einen Punkt enthalten muss. function FormularCheck_Bestellung(summe) { var f=document.forms[0]; if(f.kunde.value=="" || var d=document.forms[0]; f.email.value=="" || var l=d.length; f.email.value.indexOf("@")==-1 || for(i=0;i<l-1;i++) { f.email.value.indexOf(".")==-1 || if(d.elements[i].value!="" && (is NaN(d.elements[i].value) || parse Int(d.elements[i].value)<=0)) { alert("Eingabefehler:\nBitte geben f.strasse.value=="" || f.ort.value =="" || isNaN(f.plz.value) || f.plz.value.length!=5) { alert("Fehler: Geben Sie bitte Sie eine Anzahl > 0 ein!"); einen Namen,\neine E-Mail-Adresse d.elements[i].focus(); und Ihre Postadresse an!"); d.elements[i].select(); return false; break; } } } return true;} Für die Prüfung der Kundendaten ist die 86 test1=false; INTERNET PROFESSIONELL ■ APRIL 2002 else { test1=true; } if(summe==0) { alert('Ihr Warenkorb ist leer. \n else { test2=true; } if(test1==true && test2==true) else return true; { } return false; } } Interessant ist die Abfrage, ob der Gesamtbestellwert größer Null ist. Dazu wird im PHP-Skript die berechnete Summe in die Klammern der Javascript-Funktion geschrieben. Bei einem leeren Warenkorb, also einem Bestellwert von 0.00 Euro, wird das Formular nicht abgeschickt. Die Funktionen befinden sich in der Datei iproshop.js. Sie wurden auf die Browserversionen von Internet Explorer 5+, Netscape 4.x und 6.x, Mozilla 0.9.7 und Opera 5.x und 6 abgestimmt. Daneben kommt noch eine spezielle Funktion zur farblichen Formatierung der Textfelder zum Einsatz. Die Funktion Textfeldmarker() verwendet Javascript für dynamische Style-Zuweisungen und ist nur für den Internet Explorer bestimmt. Unter Netscape 6.x und Mozilla können diese eher kosmetischen Effekte allein auf der Basis von CSS erreicht werden (siehe iproshop.css). Opera und Netscape 4.x ignorieren die Formatierung von Formularfeldern mit CSS weitgehend und werden nicht berücksichtigt.