Artikel - Detailansicht

Icon Aktuelles Aufbau eines Warenkorbs I

Warenkörbe werden meist in eCommerce-Anwendung benötigt, wo man für den jeweiligen Sitebesucher kurzzeitig eine Auswahl an (Shop)-Artikeln speichern will. Dabei werden die ausgewählten Waren (Produkt, Menge, Preis) in einer Session oder Client-Variable (oder mehrere) gespeichert, so dass der Datensatz auf jeder Seite vorhanden ist.
Das folgende Warenkorbsystem inkl. Demoshop soll das Prinzip genauer erläutern. Der gezeigte Warenkorb lässt sich dabei leicht in eigenen Anwendungen integrieren, da alle Funktionen in einer Klasse (zusammengehöriger Satz Customtags) gekapselt sind.

die Datenbank
Zu jedem Shop gehört natürlich eine Datenbank, in unserem Fall eine einfache Access-DB mit extrem einfachen Design.
Die Tabelle mit den Artikeln heist TArticle und besitzt die Spalten:

pkAID: Artikel-ID/Primärschlüssel
sTitle: Artikelbezeichnung, String
sCategory: Kategoriebezeichnung, String
iPrice: Preis, Währung

Dort befinden sich alle Artikel des Shops.

Der Warenkorb
Die Funktionen des Warenkorbs werden als Customtags in der Klasse ShoppingCard gekapselt. Als 'Klasse' dient hier einfach mal ein Verzeichniss und die Customtags selbst entsprechen dann den 'Methoden' der Klasse. Die Klasse ShoppingCard besitzt folgende Methoden (Funktionen) die durch Dateien gleichen Namens implementiert werden:

add (add.cfm) : fügt einen Artikel zum Warenkorb hinzu
clear (clear.cfm): löscht den Warenkorb
getQuery (getQuery.cfm): liefer ein Queryset mit dem Inhalt des Warenkorbs
getRecordcount (getRecordcount.cfm): liefert die Anzahl der Artikel im Warenkorb
remove (remove.cfm): entfernt einen Artikel aus dem Warenkorb


Wir müssen im Warenkorb 2 Informationen speichern, die Artikel-ID des eingeladenen Artikels und die Anzahl.
Alle anderen Daten stehen in der Datenbank und werden deshalb nicht im Warenkorb gespeichert, obwohl das durchaus auch möglich wäre. Wir vermeiden dadurch jedoch Redundanz in den Daten.
Zur Speicherung dieser Informationen benutzen wir eine Struktur, in der die Artikel-ID der Key und die Artikelanzahl der Wert zum Key ist.
Zur persistenten Speicherung benutzen wir die Clientvariable client.wCard in der die Struktur als WDDX-Paket abgelegt wird (Clientvariablen können keine Strukturen direkt speichern).

Die Funktionen im einzelnen:

ShoppingCard.add
Die Methode add dient zum speichern eines Artikels im Warenkorb. Dazu wird die Artikel-ID und die Anzahl als Parameter übergeben. Zuerst wird, wenn bereits ein Warenkorb (ein WDDX-Paket) in der Variable client.wCard vorhanden ist, dieser in eine Struktur umgewandelt. Ist kein Warenkorb vorhanden (Client.wCard is ""), wird eine neue Struktur angelegt:

<cfparam name="client.wCard" type="string" default="">
<cfparam name="attributes.AID" type="numeric">
<cfparam name="attributes.iCount" type="numeric">

<cfif len(client.wCard)>
 <!--- eine Card ist bereits vorhanden --->
  <cfwddx action="WDDX2CFML" input="#client.wCard#" output="strCard">
<cfelse>
  <!--- neuen Card anlegen --->
  </cfif>

<!--- nachsehen, ob artikel auch existiert --->
<cfquery name="qCheck" datasource="#REQUEST.sDSN#">
select pkAID  from TArticle where pkAID =#attributes.AID#
</cfquery>
  
<cfif qCheck.recordcount>
  <!--- daten speichern --->
  <cfset strCard[attributes.AID]=attributes.iCount>

  <!--- persistent speichern --->
  <cfwddx action="CFML2WDDX" input="#strCard#" output="dummy">
  <cfset client.wCard=dummy>
<cfelse>
  <cfabort showerror="Artikel nicht vorhanden">
</cfif>

Dann wird überprüft (kann auch entfallen), ob die übergebene Artikel-ID auch in der DB existiert und diese dann als neuer Key in der Struktur angelegt. Dazu wird zur Artikel-ID noch die Anzahl gespeichert. Am Schluss wird die Struktur (strCard) wieder als WDDX-Paket in Client.wCard gespeichert.

ShoppingCard.clear
Die Methode clear dient zum Löschen des Warenkorbs und besteht lediglich aus einem einfachen:

<cfset client.wCard="">

ShoppingCard.getQuery
Die Methode getQuery liefert ein Queryset mit dem aktuellen Inhalt des Warenkorbs. Dabei werden in diesem Querysets aber die kompletten Artikeldaten und der Gesamtpreis pro Artikel gleich mitgeliefert.

<cfparam name="client.wCard" type="string" default="">

<!--- Name des gewuenschten Query-Namen --->
<cfparam name="attributes.r_sQuery" type="string">

<cfif len(client.wCard)>
   <!--- ein Card ist bereits vorhanden --->
  <cfwddx action="WDDX2CFML" input="#client.wCard#" output="strCard">
<cfelse>
   <!--- leeres Queryset zurueckliefern, als zeichen,das nix da ist --->
   <cfset evaluate("caller.#attributes.r_sQuery#=QueryNew('x')")>
   <cfexit>
</cfif>

<!--- temporaeres Queryset mit Platzhaltern erzeugen --->
<cfquery name="qTMP" datasource="#REQUEST.sDSN#">
select pkAID as AID,sTitle, sCategory, 1 as iCount , iPrice, 1 as iSum
  from TArticle
  where TArticle.pkAID in(
  <cfloop collection="#strCard#" item="AID">
   #AID#,
  </cfloop>
  0
  )
</cfquery>

<!--- jetzt noch die redundanten Daten reinschreiben --->
<cfloop query="qTMP">
   <cfset QuerySetCell(qTMP, "iCount", strCard[qTMP.aid],qTMP.currentrow )>
   <cfset QuerySetCell(qTMP, "iSum", strCard[qTMP.aid]*qTMP.iPrice,qTMP.currentrow )>
</cfloop>

<!--- das Queryset im Caller-Scope erzeugen --->
<cfset evaluate("caller.#attributes.r_sQuery#=qTmp")>



Zuerst wird wie schon beschrieben wieder der Warenkorb in eine Struktur umgewandelt. Da ein Queryset zurückgeliefert werden soll, erzeugen wir durch eine Abfrage (qTMP) ein Queryset mit den Daten der Artikel aus der DB. Dort wo dann später noch Daten dazu müssen, die wir im Warenkorb gespeichert haben, lassen wir im Queryset 'Platz' durch Dummywerte. Im anschliessenden Loop werden die redundaten Daten, die sich berechnen lassen und deshalb besser nicht fest gespeichert werden, in das Queryset geschrieben. Dadurch erhalten wir als Ergebnis von getQuery ein handliches Queryset mit allen nötigen Informationen.

ShoppingCard.getRecordcount
Mit getRecordcount erhalten wir die aktuelle Anzahl gespeicherter Artikel. Als Parameter muss ein Variablenname für den Rückgabewert angegeben werden:

<cfparam name="client.wCard" type="string" default="">
<cfparam name="attributes.r_sReturn" type="string">

<cfif len(client.wCard)>
   <!--- ein Card ist bereits vorhanden --->
   <cfwddx action="WDDX2CFML" input="#client.wCard#" output="strCard">

   <!--- StructCount() liefert die Anzahl der Artikel  --->
   <cfset evaluate("caller.#attributes.r_sReturn#=StructCount(strCard)")>
   <cfexit>
<cfelse>
   !--- nix drinn, dann 0 liefern --->
   <cfset evaluate("caller.#attributes.r_sReturn#=0")>
   <cfexit>
</cfif>


ShoppingCard.remove
Bleibt noch die Methode remove, mit der man wieder einen Artikel aus dem Warenkorb entfernen kann. Dazu muss die Artikel-ID als Parameter übergeben werde, die dann aus der Struktur gelsöcht wird:


<cfparam name="client.wCard" type="string" default="">
<cfparam name="attributes.AID" type="numeric">

<cfif len(client.wCard)>
   <!--- ein Card ist bereits vorhanden --->
   <cfwddx action="WDDX2CFML" input="#client.wCard#" output="strCard">
<cfelse>
   <!--- neuen Card anlegen --->
   <cfexit>
</cfif>

<!--- artikel loeschen --->
<cfset StructDelete(strCard, attributes.AID)>

!--- persistent speichern --->
<cfwddx action="CFML2WDDX" input="#strCard#" output="dummy">
<cfset client.wCard=dummy>


Benutzung der Klasse ShoppingCard
Zuerst muss das ganze Verzeichnis ShoppingCard im Customtag-Verzeichnis installiert werden, hier im Verzeichnis Customtags/Shop/.

Dann ergeben sich folgende Aufrufe (mit Beispielwerten):

4 mal Artikel Nr 13 ablegen:
<cfmodule name="Shop.shoppingCard.add" iCount="4" AID="13">

Warenkorb komplett löschen:
<cfmodule name="Shop.shoppingCard.clear">

Warenkorb-Daten ausgeben (Queryset qCard wird erzeugt):
<cfmodule name="Shop.shoppingCard.getQuery" r_sQuery="qCard">

Abfrage der Anzahl (iRecordcount wird erzeugt)
<cfmodule name="Shop.shoppingCard.getRecordcount" r_sReturn="iRecordcount">

Artikel Nr 13 wird aus dem Warenkorb entfernt:
<cfmodule name="Shop.shoppingCard.remove" AID="13">

Einen Punkt gibt es noch zu beachten, wenn man in einer Applikation die ShoppingCard benutzen will.
Die Clientvariablen müssen aktiviert sein (<cfapplication>) und die Variable REQUEST.sDSN muss einen gültigen DSN zur Artikel-DB enthalten. Z.B:
<cfset REQUEST.sDSN="ShoppingCard">

In den Dateien add.cfm und getQuery.cfm muss der Code dann noch an die jeweilige Datenbankstruktur angepasst werden (Tabellenname,Spaltenname usw.)

Im 2. Teil wird mit hilfe dieser Funktionen ein Grundskelett eines Shops implementiert werden.


Download DB+Dateien

steffen goldfuss steffen@goldfuss.de - 10.07.2001

Zurück


Das deutsche ColdFusion-Forum cfml.de ist das Portal für Einsteiger und Experten zum Thema ColdFusion und der ColdFusion Markup Language (CFML).

© 2017 Webdesign & Hosting: CHC ONLINE Kassel | SOLVA Content-Management-System CMS
Urlaub-Angebote.de - Urlaub mit Bestpreis-Garantie buchen