I've put together a quick example of how I'd go about it.
Save the two files below as shoppingcart.cfc and callingpage.cfm in the same directory.
Watch out for line wrapping problems.
Spike
shoppingcart.cfc
************************************************************
<cfcomponent displayname="shoppingCart">
<cfset init()>
<cffunction name="init" access="public" output="false" returntype="boolean" hint="Initializes the cart if it has not been initialized yet">
<cfif not isDefined('instance')>
<cfset instance = structNew()>
<cfset instance.aItems = arrayNew(1)>
<cfset instance.timestamp = Now()>
<cfset instance.IDs = "">
</cfif>
<cfreturn true>
</cffunction>
<cffunction name="addItem" access="public" output="false" returntype="boolean" hint="Adds an item to the cart. A cart item is a structure with any number of keys. The only required key is 'ID' which must be uniqe for every item in the cart.">
<cfargument name="item" type="struct" required="yes">
<!--- Make sure the item has an id and that the id is unique --->
<cfif not structKeyExists(arguments.item,'id')>
<cfthrow type="shoppingCart.invalidItem" message="The item does not have an id key" detail="All items added to the shopping cart must have a unique ID key to ensure that duplicate items cannot be created and multiple items are not deleted if the user refreshes the page.">
</cfif>
<cfif listFind(instance.IDs,arguments.item.id)>
<cfthrow type="shoppingCart.invalidItem" message="The item does not have a unique id key" detail="All items added to the shopping cart must have a unique ID key to ensure that duplicate items cannot be created and multiple items are not deleted if the user refreshes the page.">
</cfif>
<cfset instance.IDs = listAppend(instance.IDs,arguments.item.id)>
<cfreturn arrayAppend(instance.aItems,duplicate(arguments.item))>
</cffunction>
<cffunction name="removeItem" access="public" output="false" returntype="boolean" hint="Removes an item from the cart based on the ID passed in.">
<cfargument name="id" type="string" required="yes">
<cfset var index = "">
<!--- Make sure the item has an id and that the id is unique --->
<cfif NOT listFind(instance.IDs,arguments.id)>
<cfthrow type="shoppingCart.invalidItemID" message="The item you tried to delete does not exist" detail="The item id passed to the removeItem() method does not correspond to any items in the cart.">
</cfif>
<cfset index = listFind(instance.IDs,arguments.id)>
<cfreturn arrayDeleteAt(instance.aItems,index)>
</cffunction>
<cffunction name="getCartItems" access="public" output="false" returntype="array" hint="Returns an array of items in the order they were added to the cart">
<cfreturn instance.aItems>
</cffunction>
<cffunction name="getTimeStamp" access="public" output="false" returntype="date" hint="Returns the timestamp when the cart was created">
<cfreturn instance.timestamp>
</cffunction>
<cffunction name="clearCart" access="public" output="false" returntype="boolean" hint="Clears the cart removing all items">
<cfset instance.aItems = arrayNew(1)>
<cfreturn true>
</cffunction>
</cfcomponent>
*****************************************************************
callingpage.cfm ***************************************************************** <cfapplication name="cartexample" sessionmanagement="yes">
<cfset session.cart = createObject('component','shoppingcart')>
<cfdump var="#session.cart.getCartItems()#" label="After Initialization">
<cfset firstID = createUUID()> <cfset myItem = structNew()> <cfset myItem.priceperunit = 120> <cfset myItem.name = "Some useful thing"> <cfset myItem.quantity = 2> <cfset myItem.id = firstID>
<cfset session.cart.addItem(myItem)>
<cfdump var="#session.cart.getCartItems()#" label="After adding first item">
<cfset secondID = createUUID()> <cfset myItem = structNew()> <cfset myItem.priceperunit = 30> <cfset myItem.name = "Another useful thing"> <cfset myItem.quantity = 1> <cfset myItem.id = secondID>
<cfset session.cart.addItem(myItem)>
<cfdump var="#session.cart.getCartItems()#" label="After adding second item">
<cfset thirdID = createUUID()> <cfset myItem = structNew()> <cfset myItem.priceperunit = 10> <cfset myItem.name = "A third useful thing"> <cfset myItem.quantity = 25> <cfset myItem.id = thirdID>
<cfset session.cart.addItem(myItem)>
<cfdump var="#session.cart.getCartItems()#" label="After adding third item">
<cfset session.cart.removeItem(secondID)>
<cfdump var="#session.cart.getCartItems()#" label="After removing second item">
<cfset session.cart.clearCart(secondID)>
<cfdump var="#session.cart.getCartItems()#" label="After clearing cart"> ******************************************************************
Beattie, Barry wrote:
thanx again Mark. It's leading to a couple of more questions, I'm afraid...
Neither - you aren't calling the method on a CFC. You are trying to call
it on a struct.
you've confused me now. The only thing I've done different from usual is not used an argument in invoking the component and the CFC not having properties. Perhaps I'm getting confused with CFC interfaces seemimg to be like structs themselves, not like real objects eg: COM (actually, they feel more like VBScript classes than objects).
<cfproperty name="aProducts" type="array"> <!--- contructor ---> <cfscript> //place to store my carts this.aProducts = ArrayNew(1); </cfscript>
Ummm... why the array? is this for an array of structures or a struct of
arrays?
<!--- application.cfm --->
<cfif NOT isDefined("session.cart")> <cfscript> session.cart = CreateObject(type, "com.Cart"); </cfscript> </cfif>
- Hence all data is stored in the CFC - and is specific TO the CFC, and
nothing else (which gives lower coupling).
so the instance is stored in the session? How does session.cart get updated with new cart contents within the CFC? and what would you do if cookies or a db have to be used instead? you've made a good point about the loose coupling but it's satisfying the other side (tight cohesion) that worries me on this bit.
thanx barry.b
-----Original Message----- From: Mark M [mailto:[EMAIL PROTECTED] Sent: Monday, 29 September 2003 12:18 PM To: CFAussie Mailing List Subject: [cfaussie] Re: CFC error: "Method selection Exception" (was: Shopping carts: Arr ays Vs Structs)
1) so I'm calling the method wrong? or not invoking the component correctly?
Neither - you aren't calling the method on a CFC. You are trying to call it
on a struct. Hence the error. Dump out the 'objCart' variable, and I think you
will find what I mean.
2) >> A shopping cart should only manage the shopping cart. It shouldn't look at if it exists or not.
yes good point but I was trying to tie the storage of cart data totally into the CFC. IMHO only the CFC should care how the cart data is stored and not be dependant on other files. The CFC becomes the data store interface. If the chosen storage doesn't exist, create it.
That is fine - however I would have built it like this:
<!--- component cart --->
<cfcomponent displayname="Cart">
<cfproperty name="aProducts" type="array">
<!--- contructor --->
<cfscript>
//place to store my carts
this.aProducts = ArrayNew(1);
</cfscript>
<cffunction name="AddToCart" access="public" output="false">
<cfargument name="key" required="true" type="numeric">
<cfargument name="value" required="true" type="numeric">
<!--- add the item --->
<cfscript>
StructInsert(this.aProducts, arguments.key, arguments.value);
</cfscript>
</cffunction>
</cfcomponent>
<!--- application.cfm --->
<cfif NOT isDefined("session.cart")> <cfscript> session.cart = CreateObject(type, "com.Cart"); </cfscript> </cfif>
- Hence all data is stored in the CFC - and is specific TO the CFC, and
nothing else (which gives lower coupling).
HTH
Mark
--- You are currently subscribed to cfaussie as: [EMAIL PROTECTED] To unsubscribe send a blank email to [EMAIL PROTECTED]
MX Downunder AsiaPac DevCon - http://mxdu.com/
--- You are currently subscribed to cfaussie as: [EMAIL PROTECTED] To unsubscribe send a blank email to [EMAIL PROTECTED]
MX Downunder AsiaPac DevCon - http://mxdu.com/
