Solved

options in cart, trailblazzyr55 or dgrafx?

Posted on 2006-11-29
8
217 Views
Last Modified: 2013-12-24
Hi, I have an issue which is leaving me scratching my head! the code below was given to me as an example by trailblazzyr55, thanks

Its works like this…
1) to this page: http://www.merlindirect.com/packaging/Large-Christmas-Tree.cfm
2)select a option i.e. red, and add to basket, view cart and its all fine right!

The problem

1) Go to this page again after clearing your cart: http://www.merlindirect.com/packaging/Large-Christmas-Tree.cfm
2) Add the item to the cart ‘without’ selecting any options this time.
3) view cart, no option is in cart, that’s find because you didn’t select one!
4) go back to the product this time add the item again this time with a option say red.
5) what you should have now is 2 items in the basket (one with option red one without), but both are the same it just added to the qty of the first item!


now i still want it to add to the qty of the product if its the same product, but if its same product with different options it should be treated as another item. :(

Any help on this one? Thanks

Add to cart code...



<!--- mock form parameters being passed in, default these to "" when forms are being passed. qty default 0 or 1 --->  
<!---<cfparam name="form.productid" default="4567">
<cfparam name="form.qty" default="1">
<cfparam name="form.productOptionId" default="23,34,32">--->

<!--- if cart session does not exist, create it --->
<cfif not structkeyexists(session,"cartItem")>
     <cfset session['cartItem'] = structnew()>
</cfif>


<!---gets option id's from product form--->
<cfif IsDefined('form.optVal')  and form.optVal GT 0>
  <cfset productOptionId0 = Arraynew(1)>
  <cfset val = #form.optVal# - 1>
  <cfloop from="0" to="#val#" index=this>
    <cfset Vsel = form.sel0>
    <cfif isDefined('form.sel0')>
      <cfset formval = Evaluate("form.sel" & this)>
      <cfset optvals = ListFirst(formval,"*")>
    </cfif>
    <cfset ArrayAppend( productOptionId0, "#optvals#" ) />
  </cfloop>
  <cfset optionList = ArrayToList(productOptionId0)>
  <cfoutput> #optionList#
    <cfparam name="form.productOptionId" default="#optionList#,">
  </cfoutput>
</cfif>

<!--- if cart item does not exist, create it --->
<cfif structkeyexists(form,"productid") and form['productid'] neq "" and structkeyexists(form,"qty") and form['qty'] gt 0>
     <!--- create default node for product id --->
     <cfset itemNode = "pCode_#form['productid']#_1">
     <!--- if no node exists for the given product, create it. --->
     <cfif not structkeyexists(session['cartItem'],itemNode)>
          <!--- define new node as a struct --->
          <cfset session['cartItem'][itemNode] = structnew()>
          <cfset session['cartItem'][itemNode]['aQty'] = form['qty']>
          <!--- grab the product info based on id --->
          <cfquery name="getProd" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
          SELECT prodID,[name] AS pName,price,saleprice
          FROM products
          WHERE prodID = #form['productid']#
          </cfquery>
          <!--- populate the product node with info from the query, check if there's a sale price --->
          <cfif getProd.recordcount>
               <cfset session['cartItem'][itemNode]['aName'] = getProd.pName>
                     <cfset session['cartItem'][itemNode]['prodId'] = #form['productid']#>
               <cfif getProd.saleprice gt 0>
                    <cfset session['cartItem'][itemNode]['aPrice'] = getProd.saleprice>
               <cfelse>
                    <cfset session['cartItem'][itemNode]['aPrice'] = getProd.price>
               </cfif>
          </cfif>
          <!--- if the product has options being passed, create an options node, in the product node --->
          <cfif structkeyexists(form,"productOptionId") and listlen(form['productOptionId']) gte 1>
               <cfset optionsList = form['productOptionId']>
               <cfset session['cartItem'][itemNode]['aOpList'] = optionsList>
               <!--- loop over option ids populate options with name and price values --->
               <!---|||||||||||||| CAUTION ||||||||||||||||||--->
               <!--- "optionname" was a field I added so I didn't have to join your other tables to get the name --->
               <!--- you'll have to create the join to grab the name here before it'll work --->
               <cfloop from="1" to="#listlen(optionsList)#" index="i">
                    <cfset optionElem = listgetat(optionsList,i)>
                    <cfset session['cartItem'][itemNode]['bOption'&optionElem] = structnew()>
                    <cfquery name="getOptions" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
                                    SELECT options.optionId, options.name, optionvalues.valueId, optionvalues.value, optionvalues.optionId, productoptions.valueId, productoptions.productOptionId, productoptions.optionPrice
                                    FROM options
                                    JOIN optionvalues ON options.optionId = optionvalues.optionId
                                    JOIN productoptions ON optionvalues.valueId = productoptions.valueId
                                    WHERE productOptionId = #optionElem#
                    </cfquery>
                    <cfif getOptions.recordcount>
                         <cfset session['cartItem'][itemNode]['bOption'&optionElem]['name'] = getOptions.value>
                         <cfset session['cartItem'][itemNode]['bOption'&optionElem]['price'] = getOptions.optionPrice>
                    </cfif>
               </cfloop>
          </cfif>
     <!--- check for existing cart item with options --->
     <cfelseif structkeyexists(session['cartItem'],itemNode) and structkeyexists(session['cartItem'][itemNode],"aOpList")>
          <cfset currentNodes = structkeylist(session['cartItem'])>
          <cfset foundNode = false>
          <!--- loop over current products in cart to see if there are any absolute matches --->
          <cfloop from="1" to="#listlen(currentNodes)#" index="j">
               <cfif listgetat(listgetat(currentNodes,j),2,"_") eq form['productid'] and compare(session['cartItem'][listgetat(currentNodes,j)]['aOpList'],form['productOptionId']) eq 0>
                    <cfset itemNode = listgetat(currentNodes,j)>
                    <cfset foundNode = true>
                    <cfbreak>
               </cfif>
          </cfloop>
          <!--- if there's already an existing product with the same options, increment the qty --->
          <cfif foundNode>
               <cfset session['cartItem'][itemNode]['aQty'] = form['qty'] + session['cartItem'][itemNode]['aQty']>    
          <!--- otherwise create a new item, increment dup item count, create new product node similar to above --->
          <cfelse>
               <!--- increments the unique product id if one already exists --->
               <cfset currentKeys = structkeylist(session['cartItem'])>
               <cfset focusCount = 0>
               <cfloop from="1" to="#listlen(currentKeys)#" index="x">
                    <cfset focusArea = listgetat(listgetat(currentKeys,x),2,"_")>
                    <cfif focusArea eq form['productid']>
                         <cfset focusCount = focusCount + 1>
                    </cfif>
               </cfloop>
               <cfset focusCount = focusCount + 1>
               <cfset itemNode = "pCode_#form['productid']#_#focusCount#">
               <cfset session['cartItem'][itemNode] = structnew()>
               <cfset session['cartItem'][itemNode]['aQty'] = form['qty']>
               <cfquery name="getProd" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
               SELECT prodID,[name] AS pName,price,saleprice
               FROM products
               WHERE prodID = #form['productid']#
               </cfquery>
               <cfif getProd.recordcount>
                    <cfset session['cartItem'][itemNode]['aName'] = getProd.pName>
                              <cfset session['cartItem'][itemNode]['prodId'] = #form['productid']#>
                    <cfif getProd.saleprice gt 0>
                         <cfset session['cartItem'][itemNode]['aPrice'] = getProd.saleprice>
                    <cfelse>
                         <cfset session['cartItem'][itemNode]['aPrice'] = getProd.price>
                    </cfif>
               </cfif>
               <cfif structkeyexists(form,"productOptionId") and listlen(form['productOptionId']) gte 1>
                    <cfset optionsList = form['productOptionId']>
                    <cfset session['cartItem'][itemNode]['aOpList'] = optionsList>
                    <cfloop from="1" to="#listlen(optionsList)#" index="i">
                         <cfset optionElem = listgetat(optionsList,i)>
                         <cfset session['cartItem'][itemNode]['bOption'&optionElem] = structnew()>
                         <!---|||||||||||||| CAUTION ||||||||||||||||||--->
                                 <!--- "optionname" was a field I added so I didn't have to join your other tables to get the name --->
                                 <!--- you'll have to create the join to grab the name here before it'll work --->
                                 <cfquery name="getOptions" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
                                          SELECT options.optionId, options.name, optionvalues.valueId, optionvalues.value, optionvalues.optionId, productoptions.valueId, productoptions.productOptionId, productoptions.optionPrice
                                          FROM options
                                          JOIN optionvalues ON options.optionId = optionvalues.optionId
                                          JOIN productoptions ON optionvalues.valueId = productoptions.valueId
                                          WHERE productOptionId = #optionElem#                                          
                         </cfquery>
                         <cfif getOptions.recordcount>
                              <cfset session['cartItem'][itemNode]['bOption'&optionElem]['name'] = getOptions.value>
                              <cfset session['cartItem'][itemNode]['bOption'&optionElem]['price'] = getOptions.optionPrice>
                         </cfif>
                    </cfloop>
               </cfif>
          </cfif>
     <!--- if a product is already in the cart without options, just increment the product quantity --->
     <cfelseif structkeyexists(session['cartItem'],itemNode) and not structkeyexists(session['cartItem'][itemNode],"aOpList")>
          <cfset currentItemsCount = session['cartItem'][itemNode]['aQty']>
          <cfset session['cartItem'][itemNode]['aQty'] = form['qty'] + currentItemsCount>
     </cfif>
</cfif>




<cflocation url="#form.return#&success=true" addtoken="no">
0
Comment
Question by:pigmentarts
  • 4
  • 4
8 Comments
 
LVL 12

Author Comment

by:pigmentarts
ID: 18035886
done it, was checking for the wrong thing here:

 <cfparam name="form.productOptionId" default="#optionList#,">

lol. i will chnage this into another question then, it it possible to make the above a custom_tag?

0
 
LVL 20

Expert Comment

by:trailblazzyr55
ID: 18036408
since you're using sessions, I may recommend possibly creating an XML cart, and then creating a few methods in a CFC that would be like convenience methods for adding, updating, removing, etc...

This way you could easily reuse the code anywhere in your pages just by calling your CFC's....
you could probably put the above code into a custom tag, however if I was going to go through doing that, I'd probably lean more towards the CFC method.
In fact I'd always lean more towards using CFC's unless I was stuck on CF5 or earlier for a project... then I'd think about a custom tag...

want an example?
~trail
0
 
LVL 12

Author Comment

by:pigmentarts
ID: 18036595
cool, so i simply put this code in a .cfc use xml to sent it.
0
 
LVL 20

Expert Comment

by:trailblazzyr55
ID: 18036963
It'd be a code rewrite (unfortunately) however it'd probably be less code and more flexible...

Give me a few here and I'll put together an example...
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 20

Expert Comment

by:trailblazzyr55
ID: 18037865
can you do me a favor and just verify this is correct...?

the cart info you want to track is this right?

Product Name,  Product ID, Product Price, Sale Price, Product Quantity
    > Product Option Name, Product Option ID, Product Option Price

Shipping Total, Shipping Subtotal, Shipping Method
0
 
LVL 12

Author Comment

by:pigmentarts
ID: 18038535
sorry phones ringing of the hook here,

yep thats right, at the moment, we have a product page which send prodId option and qty, this is that page................


<form name="prod" action="../additem.cfm" method="post">
    <cfoutput>
      <input type="hidden" name="return" value="http://www.merlindirect.com/packaging/product_page.cfm?prodId=#prodId#&catId=#catId#&manId=#manId#" />
    <input type="hidden" name="productId" value="#prodId#" />
   
 
      <div id="productimage">
      <cfif images.RecordCount GT 0>
        <cfloop query="images" startrow="1" endrow="1">
          <!-- loop all images till EOF -->
             <img src="../images/products/#name#.jpg" alt="#name#" width="98%"/> <br />
        </cfloop>
        <!-- end loop -->
        <cfelse>
        <!-- else no image to to display -->
        <img src="../images/default.gif" alt="No Image available" width="70%" />
      </cfif>
    </div>
      
      
    <div class="buynow">
      <!---if product options have been cal--->
      <cfif price GT 0>
        <cfif retailPrice GT 0>
          <p><span class="crossout">Retail Price: &pound;#LSCurrencyFormat(val(retailPrice), "none")#</span></p>
        </cfif>
        <p><b>Price</b>:
          <cfif salePrice GT 0>
            <span class="crossout">&pound;#LSCurrencyFormat(val(price), "none")#</span><br />
            <p class="error">Sale Price: <b>&pound;#LSCurrencyFormat(val(salePrice), "none")#</b></p>
            <cfelse>
            <b>&pound;#LSCurrencyFormat(val(price), "none")#</b>
          </cfif>
        </p>
        <!---set the price for the buy now button to use--->
        <cfscript>
                  if(salePrice GT 0) {
                        buyPrice = #salePrice#;
                  }
                  else {
                        buyPrice = #price#;
                  }
            </cfscript>
        <!---if no price was found for the product--->
        <cfelse>
        <div class="textalignL"><p>Sorry this product is not available for purchase online.</p><p><b>Please call</b> Tel: 0845 363 1063 for more information.</p></div>
        <cfscript>
              buyPrice = 0;            
            </cfscript>
      </cfif>
   
    <!---hidden price sent to shopping cart--->
    <input type="hidden" name="productpr" value="#LSNumberFormat(buyPrice, "_.__")#" />
    <br />
    <cfif price GT 0>
      <label>Quantity&nbsp;&nbsp;<input name="qty" type="text" value="1" size="1" maxlength="2" onchange="AddTo(this,'TotalIP');" /></label><br />
        <cfoutput>
        <label class="clear">Total Price &nbsp;&nbsp;&pound;<input type="text" value="#LSNumberFormat(buyPrice, "_.__")#" name="TotalIP" readonly="yes" size="7" maxlength="8" /></label>
       <div class="vat">(*all prices inc VAT)</div>
       </cfoutput>
      <input name="Buy now" value="Buy now" type="image" src="../images/button-add.gif" alt="Add to Cart" width="62%" />
    </cfif>
      
      </div>
  </cfoutput>

 
  <!---product options select boxes--->
  <!---form for product options--->
  <cfset opts = 0>
  <table width="99%" border="0" class="clearall">
  <tr><td><cfif locals.optionsvals.RecordCount GT 0><h2>Product Options</h2></cfif></td></tr>
  <cfoutput query="locals.optionsvals" group="name">
    <cfinvoke component="#component#" method="getValues" returnvariable="getValues">
    <cfinvokeargument name="optId" value="#optionId#">
    </cfinvoke>
    <cfif getValues.RecordCount GT 0>
      <cfif getValues.optionPrice GT 0>
        <cfset pricePresent = TRUE>
        <cfelse>
        <cfset pricePresent = FALSE>
      </cfif>
    </cfif>

<tr>
  <td width="25%"><p class="textalign">#name#:</p></td>
  <td width="73%">
      <select name="sel#opts#" onchange="AddTo(this,'TotalIP');" size="1">
      <option value="">- - - - - - - - - - - - - - - - - -</option>
      <cfloop query="getValues">
        <cfscript>
                  if(getValues.optionPrice GT 0) {
                        optValue = '#LSNumberFormat(getValues.optionPrice, "_.__")#';
                        optName = '#getValues.value#';
                  }
                  else if(pricePresent IS TRUE) {
                        optValue = '#LSNumberFormat(0.00)#';
                        optName = '#getValues.value#';
                  }
                  else {
                        optValue = '#LSNumberFormat(getValues.optionPrice, "_.__")#';
                        optName = '#getValues.value#';
                  }
            </cfscript>
        <option value="#productOptionId#*£#optValue#">#optName#
        <cfif #optValue# GT 0>
          £#optValue#
        </cfif>
        </option>
      </cfloop>
    </select>
  </td>
</tr>

    <cfset opts = opts + 1>
  </cfoutput>
 
  </table>
  <cfoutput><input name="optVal" type="hidden" value="#opts#" /></cfoutput>
   </form>












after that it gets posted to this............... (which now works right lol)















<!---
****************************************************
  EXAMPLE SHOPPING CART
****************************************************--->

<!------>

<!--- mock form parameters being passed in, default these to "" when forms are being passed. qty default 0 or 1 --->  
<!---<cfparam name="form.productid" default="4567">
<cfparam name="form.qty" default="1">
<cfparam name="form.productOptionId" default="23,34,32">--->

<!--- if cart session does not exist, create it --->
<cfif not structkeyexists(session,"cartItem")>
     <cfset session['cartItem'] = structnew()>
</cfif>


<!---gets option id's from product form--->
<cfif structkeyexists(FORM, "optVal") AND FORM['optVal'] GT 0 AND FORM['optVal'] NEQ "">
  <cfset productOptionId0 = Arraynew(1)>
  <cfset val = #form.optVal# - 1>
  <cfloop from="0" to="#val#" index=this>
    <cfset Vsel = form.sel0>
    <cfif isDefined('form.sel0')>
      <cfset formval = Evaluate("form.sel" & this)>
      <cfset optvals = ListFirst(formval,"*")>
    </cfif>
    <cfset ArrayAppend( productOptionId0, "#optvals#" ) />
  </cfloop>
  <cfset optionList = ArrayToList(productOptionId0)>
  <cfoutput> #optionList#
    <cfparam name="form.productOptionId" default="#optionList#,">
  </cfoutput>
</cfif>
 
<!--- if cart item does not exist, create it --->
<cfif structkeyexists(form,"productid") and form['productid'] neq "" and structkeyexists(form,"qty") and form['qty'] gt 0>
     

      
       <!--- create default node for product id --->
     <cfset itemNode = "pCode_#form['productid']#_1">
     <!--- if no node exists for the given product, create it. --->
     <cfif not structkeyexists(session['cartItem'],itemNode)>
          <!--- define new node as a struct --->
          <cfset session['cartItem'][itemNode] = structnew()>
          <cfset session['cartItem'][itemNode]['aQty'] = form['qty']>
          <!--- grab the product info based on id --->
          <cfquery name="getProd" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
          SELECT prodID,[name] AS pName,price,saleprice
          FROM products
          WHERE prodID = #form['productid']#
          </cfquery>
          <!--- populate the product node with info from the query, check if there's a sale price --->
          <cfif getProd.recordcount>
               <cfset session['cartItem'][itemNode]['aName'] = getProd.pName>
                     <cfset session['cartItem'][itemNode]['prodId'] = #form['productid']#>
               <cfif getProd.saleprice gt 0>
                    <cfset session['cartItem'][itemNode]['aPrice'] = getProd.saleprice>
               <cfelse>
                    <cfset session['cartItem'][itemNode]['aPrice'] = getProd.price>
               </cfif>
          </cfif>
          <!--- if the product has options being passed, create an options node, in the product node --->
          <cfif structkeyexists(FORM, "optVal") AND FORM['optVal'] GT 0 AND FORM['optVal'] NEQ "">
               <cfset optionsList = form['productOptionId']>
               <cfset session['cartItem'][itemNode]['aOpList'] = optionsList>
               <!--- loop over option ids populate options with name and price values --->
               <!---|||||||||||||| CAUTION ||||||||||||||||||--->
               <!--- "optionname" was a field I added so I didn't have to join your other tables to get the name --->
               <!--- you'll have to create the join to grab the name here before it'll work --->
               <cfloop from="1" to="#listlen(optionsList)#" index="i">
                    <cfset optionElem = listgetat(optionsList,i)>
                    <cfset session['cartItem'][itemNode]['bOption'&optionElem] = structnew()>
                    <cfquery name="getOptions" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
                                    SELECT options.optionId, options.name, optionvalues.valueId, optionvalues.value, optionvalues.optionId, productoptions.valueId, productoptions.productOptionId, productoptions.optionPrice
                                    FROM options
                                    JOIN optionvalues ON options.optionId = optionvalues.optionId
                                    JOIN productoptions ON optionvalues.valueId = productoptions.valueId
                                    WHERE productOptionId = #optionElem#
                    </cfquery>
                    <cfif getOptions.recordcount>
                         <cfset session['cartItem'][itemNode]['bOption'&optionElem]['name'] = getOptions.value>
                         <cfset session['cartItem'][itemNode]['bOption'&optionElem]['price'] = getOptions.optionPrice>
                    </cfif>
               </cfloop>
          </cfif>
     <!--- check for existing cart item with options --->
     <cfelseif structkeyexists(session['cartItem'],itemNode) and structkeyexists(session['cartItem'][itemNode],"aOpList")>
          <cfset currentNodes = structkeylist(session['cartItem'])>
          <cfset foundNode = false>
          <!--- loop over current products in cart to see if there are any absolute matches --->
          <cfloop from="1" to="#listlen(currentNodes)#" index="j">
               <cfif listgetat(listgetat(currentNodes,j),2,"_") eq form['productid'] and compare(session['cartItem'][listgetat(currentNodes,j)]['aOpList'],form['productOptionId']) eq 0>
                    <cfset itemNode = listgetat(currentNodes,j)>
                    <cfset foundNode = true>
                    <cfbreak>
               </cfif>
          </cfloop>
          <!--- if there's already an existing product with the same options, increment the qty --->
          <cfif foundNode>
               <cfset session['cartItem'][itemNode]['aQty'] = form['qty'] + session['cartItem'][itemNode]['aQty']>    
          <!--- otherwise create a new item, increment dup item count, create new product node similar to above --->
          <cfelse>
               <!--- increments the unique product id if one already exists --->
               <cfset currentKeys = structkeylist(session['cartItem'])>
               <cfset focusCount = 0>
               <cfloop from="1" to="#listlen(currentKeys)#" index="x">
                    <cfset focusArea = listgetat(listgetat(currentKeys,x),2,"_")>
                    <cfif focusArea eq form['productid']>
                         <cfset focusCount = focusCount + 1>
                    </cfif>
               </cfloop>
               <cfset focusCount = focusCount + 1>
               <cfset itemNode = "pCode_#form['productid']#_#focusCount#">
               <cfset session['cartItem'][itemNode] = structnew()>
               <cfset session['cartItem'][itemNode]['aQty'] = form['qty']>
               <cfquery name="getProd" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
               SELECT prodID,[name] AS pName,price,saleprice
               FROM products
               WHERE prodID = #form['productid']#
               </cfquery>
               <cfif getProd.recordcount>
                    <cfset session['cartItem'][itemNode]['aName'] = getProd.pName>
                              <cfset session['cartItem'][itemNode]['prodId'] = #form['productid']#>
                    <cfif getProd.saleprice gt 0>
                         <cfset session['cartItem'][itemNode]['aPrice'] = getProd.saleprice>
                    <cfelse>
                         <cfset session['cartItem'][itemNode]['aPrice'] = getProd.price>
                    </cfif>
               </cfif>
               <cfif structkeyexists(FORM, "optVal") AND FORM['optVal'] GT 0 AND FORM['optVal'] NEQ "">
                    <cfset optionsList = form['productOptionId']>
                    <cfset session['cartItem'][itemNode]['aOpList'] = optionsList>
                    <cfloop from="1" to="#listlen(optionsList)#" index="i">
                         <cfset optionElem = listgetat(optionsList,i)>
                         <cfset session['cartItem'][itemNode]['bOption'&optionElem] = structnew()>
                         <!---|||||||||||||| CAUTION ||||||||||||||||||--->
                                 <!--- "optionname" was a field I added so I didn't have to join your other tables to get the name --->
                                 <!--- you'll have to create the join to grab the name here before it'll work --->
                                 <cfquery name="getOptions" datasource="#dbSource#" username="#dbUsername#" password="#dbPassword#">
                                          SELECT options.optionId, options.name, optionvalues.valueId, optionvalues.value, optionvalues.optionId, productoptions.valueId, productoptions.productOptionId, productoptions.optionPrice
                                          FROM options
                                          JOIN optionvalues ON options.optionId = optionvalues.optionId
                                          JOIN productoptions ON optionvalues.valueId = productoptions.valueId
                                          WHERE productOptionId = #optionElem#                                          
                         </cfquery>
                         <cfif getOptions.recordcount>
                              <cfset session['cartItem'][itemNode]['bOption'&optionElem]['name'] = getOptions.value>
                              <cfset session['cartItem'][itemNode]['bOption'&optionElem]['price'] = getOptions.optionPrice>
                         </cfif>
                    </cfloop>
               </cfif>
          </cfif>
     <!--- if a product is already in the cart without options, just increment the product quantity --->
     <cfelseif structkeyexists(session['cartItem'],itemNode) and not structkeyexists(session['cartItem'][itemNode],"aOpList")>
          <cfset currentItemsCount = session['cartItem'][itemNode]['aQty']>
          <cfset session['cartItem'][itemNode]['aQty'] = form['qty'] + currentItemsCount>
     </cfif>
</cfif>




<cflocation url="#form.return#&success=true" addtoken="no">



then we just display it
0
 
LVL 20

Accepted Solution

by:
trailblazzyr55 earned 500 total points
ID: 18067965
hey sorry it's taken a bit to get back to you on this, I've been pretty busy lately with some projects, but meanwhile I put together a shopping cart CFC you may want to use.
below I'll show you had to use the CFC and then the code for the CFC below that...

how to use it...
------------------

on your cart action page where you want to do the updating, adding, deleting, etc...

have this code at the top...

<cfscript>
cart = createObject("component","ShoppingCart").init('ShoppingCart','#dbSource#','#dbUsername#','#dbPassword#');
if(not structKeyExists(session,"ShoppingCart")){
 cart.setCart();
}
</cfscript>

in creating the CFC

createObject("component","ShoppingCart")  >>     "ShoppingCart" is the name of the CFC, if this CFC is in another folder which it probably should be, you want to give it the actual path here

example if I have it in a folder called "ShoppingUtils" then you'd want to specify the path like so...

cart = createObject("component","ShoppingUtils.ShoppingCart").init('ShoppingCart','#dbSource#','#dbUsername#','#dbPassword#');

the init() has these parameters... ('name of cart - can be what you want','dbSource','dbUsername','dbPassword')

so anyway, then to perform actions on the cart you'd use these methods in your code...



<cfscript>
cart.setCartItem('12345', '21,31,41', 5);     //adds an item to your cart - parameters ('productID','list of option IDs',quantity)
cart.setProductQty('12345', '21,31,41', 0);  //updates quantity for an item - parameters ('productID','list of option IDs',new quantity) , set new quantity to 0 to delete the item
cart.setShipping('FedEx',21.99);                //sets the shipping for the cart - parameters ('shipping method',shipping price)
cart.setCart();                                         //call this to empty your cart
</cfscript>

these can also be used like so...

<cfset cart.setCartItem('12345', '21,31,41', 5)>
<cfset cart.setProductQty('12345', '21,31,41', 0)>
<cfset cart.setShipping('FedEx',21.99)>
<cfset cart.setCart()>

to get a struct you can loop over to display your cart, you can call this method...
I'm dumping it here as an example...

<cfdump var="#cart.getCartStruct()#">

so for example if you want to add a cart item on your page your new code might look like this...

<cfif structkeyexists(form,"productid") and form['productid'] neq "" and structkeyexists(form,"qty") and form['qty'] gt 0>
 <cfset cart.setCartItem('#form['productid']#', '', #form['qty']#)> <!--- this adds a cart item with no options --->
</cfif>

let me know if you have any questions..... here's the CFC
also keep in mind rather than looping over the cart structure to insert these to your database, you can add a method in your CFC to do this for you and all you have to do is just call it to complete your order and update your table...

for instance if you created a method in your CFC called "completeOrder()"
it would run an update query in your CFC to add the items to a table, I haven't written this, but there should be enough below to get an idea how to do it, and if you have any questions let me know, always glad to help ;o)

ShoppingCart.cfc
--------------------

<cfcomponent>
 <cffunction name="init" access="public" returntype="struct" output="false" hint="I initialize the name of the cart">
  <cfargument name="xmlCartName" type="string" required="yes">
  <cfargument name="dbSource" type="string" required="yes">
  <cfargument name="dbUsername" type="string" required="yes">
  <cfargument name="dbPassword" type="string" required="yes">
  <cfscript>
  variables.instance = structnew();
  instance['xmlCartName'] = arguments.xmlCartName;
  instance['dbSource'] = arguments.dbSource;
  instance['dbUsername'] = arguments.dbUsername;
  instance['dbPassword'] = arguments.dbPassword;
  </cfscript>
  <cfreturn this />
 </cffunction>
      
 <cffunction name="setCart" access="public" returntype="void" output="false" hint="I create a new instance of the cart">
  <cfscript>
  if(not structKeyExists(session,instance.xmlCartName))
   session[instance.xmlCartName] = structnew();
  </cfscript>
  <cfxml variable="shoppingCart">
   <orderData>
    <shipping method="" cartShipTotal="0" />
    <totals cartSubTotal="0" cartGrandTotal="0" />
   </orderData>
  </cfxml>
  <cfset session[instance.xmlCartName] = toString(shoppingCart) />
 </cffunction>
      
 <cffunction name="getCartData" access="private" returntype="string" hint="I return the string version of the cart">
  <cfreturn session[instance.xmlCartName] />
 </cffunction>

 <cffunction name="getCart" access="public" returntype="any" hint="I return an xml version of the cart">
  <cfreturn xmlParse(session[instance.xmlCartName]) />
 </cffunction>
      
 <cffunction name="setShipping" access="public" returntype="void" output="false" hint="I set the shipping for the cart">
  <cfargument name="shippingMethod" type="string" required="yes">
  <cfargument name="shippingPrice" type="numeric" required="yes">
  <cfscript>
  var xmlDoc = structnew();
  var xmlProduct = arraynew(1);
  xmlDoc = xmlParse(getCartData());
  xmlShipping = xmlSearch(xmlDoc,"/orderData/shipping");
  if(arraylen(xmlShipping)){
   xmlShipping[1].xmlAttributes['method'] = arguments.shippingMethod;
   xmlShipping[1].xmlAttributes['cartShipTotal'] = arguments.shippingPrice;
  }
  session[instance.xmlCartName] = toString(xmlDoc);
  setTotals();
  </cfscript>
 </cffunction>
      
 <cffunction name="setCartItem" access="public" returntype="void" output="false" hint="I'm called to add products and thier options to the cart">
  <cfargument name="prodId" type="string" required="yes">
  <cfargument name="productOpIdList" type="string" required="yes">
  <cfargument name="productQuantity" type="numeric" required="yes">
  <cfscript>
  var xmlProduct = arraynew(1);
  xmlProduct = verifyProdArray(arguments.prodId,arguments.productOpIdList);
  if(arguments.productQuantity gt 0){
   if(arraylen(xmlProduct)){
    updateProduct(arguments.prodId,arguments.productOpIdList);
   }else{
    setProduct(arguments.prodId,arguments.productOpIdList,arguments.productQuantity);
    setOptions(arguments.prodId,arguments.productOpIdList);
   }
  }
  setTotals();
  </cfscript>
 </cffunction>
      
 <cffunction name="setProduct" access="private" returntype="void" output="false" hint="I set the products in the cart">
  <cfargument name="prodId" type="string" required="yes">
  <cfargument name="productOpIdList" type="string" required="yes">
  <cfargument name="productQuantity" type="numeric" required="yes">
  <cfscript>
  var xmlDoc = structnew();
  var productDetailsArray = arraynew(2);
  var newNode = getNewProductNum();
  xmlDoc = xmlParse(getCartData());
  productDetailsArray = getProductArray2D(arguments.prodId);
  if(arraylen(productDetailsArray) and arraylen(productDetailsArray) eq 1){
   xmlDoc.xmlRoot.xmlChildren[newNode] = XmlElemNew(xmlDoc,"product");
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['productID'] = xmlFormat(arguments.prodId);
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['productName'] = xmlFormat(productDetailsArray[1][2]);
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['price'] = xmlFormat(productDetailsArray[1][3]);
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['quantity'] = xmlFormat(arguments.productQuantity);
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['optionList'] = xmlFormat(arguments.productOpIdList);
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['itemSubTotal'] = xmlFormat(productDetailsArray[1][3] * arguments.productQuantity);
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['optionSubTotal'] = xmlFormat(0);
   xmlDoc.xmlRoot.xmlChildren[newNode].xmlAttributes['itemTotal'] = xmlFormat(0);
  }
  session[instance.xmlCartName] = toString(xmlDoc);
  </cfscript>
 </cffunction>
      
 <cffunction name="setOptions" access="private" returntype="void" output="false" hint="I set the product options in the cart">
  <cfargument name="prodId" type="string" required="yes">
  <cfargument name="productOpIdList" type="string" required="yes">
  <cfscript>
  var i = 0;
  var xmlDoc = structnew();
  var productOptionsArray = arraynew(2);
  var xmlProduct = arraynew(1);
  xmlDoc = xmlParse(getCartData());
  xmlProduct = xmlSearch(xmlDoc,"/orderData/product[@productID=#arguments.prodId#][@optionList='#arguments.productOpIdList#']");
  productOptionsArray = getOptionArray2D(arguments.productOpIdList);
  if(arraylen(xmlProduct)){
   for(i=1;i lte arraylen(productOptionsArray);i=i+1){
    xmlProduct[1].xmlChildren[i] = xmlElemNew(xmlDoc,"option");
    xmlProduct[1].xmlChildren[i].xmlAttributes['optionId'] = xmlFormat(productOptionsArray[i][1]);
    xmlProduct[1].xmlChildren[i].xmlAttributes['optionName'] = xmlFormat(productOptionsArray[i][2]);
    xmlProduct[1].xmlChildren[i].xmlAttributes['optionPrice'] = xmlFormat(productOptionsArray[i][3]);
   }
  }
  session[instance.xmlCartName] = toString(xmlDoc);
  </cfscript>
 </cffunction>
      
 <cffunction name="updateProduct" access="private" returntype="void" output="false" hint="I update a product count if one currently exists">
  <cfargument name="prodId" type="string" required="yes">
  <cfargument name="productOpIdList" type="string" required="yes">
  <cfscript>
  var xmlDoc = structnew();
  var xmlProduct = arraynew(1);
  xmlDoc = xmlParse(getCartData());
  xmlProduct = xmlSearch(xmlDoc,"/orderData/product[@productID=#arguments.prodId#][@optionList='#arguments.productOpIdList#']");
  if(arraylen(xmlProduct)){
   xmlProduct[1].xmlAttributes['quantity'] = xmlFormat(xmlProduct[1].xmlAttributes['quantity'] + 1);
   xmlProduct[1].xmlAttributes['itemSubTotal'] = xmlFormat(xmlProduct[1].xmlAttributes['quantity'] * xmlProduct[1].xmlAttributes['price']);
  }
  session[instance.xmlCartName] = toString(xmlDoc);
  </cfscript>
 </cffunction>
      
 <cffunction name="setProductQty" access="public" returntype="void" output="false" hint="I update the quantity of a product">
  <cfargument name="prodId" type="string" required="yes">
  <cfargument name="productOpIdList" type="string" required="yes">
  <cfargument name="productQty" type="numeric" required="yes">
  <cfscript>
  var xmlDoc = structnew();
  var xmlElem = arraynew(1);
  var i = 0;
  xmlDoc = xmlParse(getCartData());
  if(arraylen(xmlDoc.xmlRoot.xmlChildren)){
   for(i=1;i lte arraylen(xmlDoc.xmlRoot.xmlChildren);i=i+1){
    xmlElem = xmlDoc.xmlRoot.xmlChildren[i];
    if(xmlElem.xmlName eq "product" and xmlElem.xmlAttributes['productID'] eq arguments.prodId and xmlElem.xmlAttributes['optionList'] eq arguments.productOpIdList){
     if(arguments.productQty gt 0){
      xmlElem.xmlAttributes['quantity'] = xmlFormat(arguments.productQty);
      xmlElem.xmlAttributes['itemSubTotal'] = xmlFormat(xmlElem.xmlAttributes['quantity'] * xmlElem.xmlAttributes['price']);
     }else{
      arraydeleteat(xmlDoc.xmlRoot.xmlChildren,i);
     }
    }
   }
  }
  session[instance.xmlCartName] = toString(xmlDoc);
  setTotals();
  </cfscript>
 </cffunction>
      
 <cffunction name="verifyProdArray" access="private" returntype="array" output="false" hint="I check for a products existance">
  <cfargument name="prodId" type="string" required="yes">
  <cfargument name="productOpIdList" type="string" required="yes">
  <cfscript>
  var xmlDoc = structnew();
  var xmlFind = arraynew(1);
  xmlDoc = xmlParse(getCartData());
  xmlFind = xmlSearch(xmlDoc,"/orderData/product[@productID=#arguments.prodId#][@optionList='#arguments.productOpIdList#']");
  </cfscript>
  <cfreturn xmlFind>
 </cffunction>

 <cffunction name="getNewProductNum" access="private" returntype="numeric" output="false" hint="I return a placeholder for a new product">
  <cfscript>
  var xmlDoc = structnew();
  var xmlNodeCount = 0;
  xmlDoc = xmlParse(getCartData());
  xmlNodeCount = arraylen(xmlDoc.xmlRoot.xmlChildren);
  </cfscript>
  <cfreturn xmlNodeCount+1>
 </cffunction>

 <cffunction name="getProductArray2D" access="private" returntype="array" output="false" hint="I get the product information based on a product ID">
  <cfargument name="prodID" type="string" required="yes">
  <cfscript>
  var returnArray = arraynew(2);
  var getProducts = "";
  </cfscript>
  <cfif len(trim(arguments.prodID))>
   <cfquery name="getProducts" datasource="#instance.dbSource#" username="#instance.dbUsername#" password="#instance.dbPassword#">
   SELECT prodID,[name] AS pName,price,saleprice
   FROM products
   WHERE prodID = #arguments.prodID#
   </cfquery>
   <cfif getProducts.recordcount>
    <cfloop query="getProducts">
     <cfset returnArray[currentrow][1] = getProducts['prodId'][currentrow]>
     <cfset returnArray[currentrow][2] = getProducts['pName'][currentrow]>
     <!--- if there's a sale price use that, otherwise use regular price --->
     <cfif len(getProducts.salePrice[currentrow]) and getProducts.salePrice[currentrow] gt 0>
      <cfset returnArray[currentrow][3] = getProducts['salePrice'][currentrow]>
     <cfelse>
      <cfset returnArray[currentrow][3] = getProducts['price'][currentrow]>
     </cfif>
    </cfloop>
   </cfif>
  </cfif>
  <cfreturn returnArray>
 </cffunction>

 <cffunction name="getOptionArray2D" access="private" returntype="array" output="false" hint="I get the options information for a product">
  <cfargument name="optionIDList" type="string" required="yes">
  <cfscript>
  var returnArray = arraynew(2);
  var getOptions = "";
  </cfscript>
  <cfif listlen(arguments.optionIDList)>
   <cfquery name="getOptions" datasource="#instance.dbSource#" username="#instance.dbUsername#" password="#instance.dbPassword#">
   SELECT options.optionId, options.name, optionvalues.valueId, optionvalues.value, optionvalues.optionId, productoptions.valueId, productoptions.productOptionId, productoptions.optionPrice
   FROM options
   JOIN optionvalues ON options.optionId = optionvalues.optionId
   JOIN productoptions ON optionvalues.valueId = productoptions.valueId
   WHERE productOptionId IN (#arguments.optionIDList#)
   </cfquery>
   <cfif getOptions.recordcount>
    <cfloop query="getOptions">
     <cfset returnArray[currentrow][1] = getOptions['optionId'][currentrow]>    <!--- option id --->
     <cfset returnArray[currentrow][2] = getOptions['value'][currentrow]>       <!--- option name --->
     <cfset returnArray[currentrow][3] = getOptions['optionPrice'][currentrow]> <!--- option price --->
     <cfset returnArray[currentrow][4] = arguments.optionIDList>                <!--- option list --->
    </cfloop>
   </cfif>
  </cfif>
  <cfreturn returnArray>
 </cffunction>

 <cffunction name="getCartStruct" access="public" returntype="struct" output="false" hint="I return a structure version of the XML shopping cart">
  <cfscript>
  var xmlDoc = structnew();
  var rtnData = structnew();
  var xmlProduct = arraynew(1);
  var xmlShipping = arraynew(1);
  var xmlTotals = arraynew(1);
  var xmlOptions = arraynew(1);
  var i = 0;
  var x = 0;
  rtnData['shipping'] = structnew();
  rtnData['totals'] = structnew();
  rtnData['products'] = structnew();
  xmlDoc = xmlParse(getCartData());
  xmlProduct = xmlSearch(xmlDoc,"/orderData/product");
  xmlShipping = xmlSearch(xmlDoc,"/orderData/shipping");
  xmlTotals = xmlSearch(xmlDoc,"/orderData/totals");
  rtnData['shipping']['method'] = xmlShipping[1].xmlAttributes['method'];
  rtnData['shipping']['cartShipTotal'] = xmlShipping[1].xmlAttributes['cartShipTotal'];
  rtnData['totals']['cartGrandTotal'] = xmlTotals[1].xmlAttributes['cartGrandTotal'];
  rtnData['totals']['cartSubTotal'] = xmlTotals[1].xmlAttributes['cartSubTotal'];
  if(arraylen(xmlProduct)){
   for(i=1;i lte arraylen(xmlProduct);i=i+1){
    rtnData['products']['product_#i#'] = structnew();
    rtnData['products']['product_#i#']['itemSubTotal'] = xmlProduct[i].xmlAttributes['itemSubTotal'];
    rtnData['products']['product_#i#']['optionList'] = xmlProduct[i].xmlAttributes['optionList'];
    rtnData['products']['product_#i#']['price'] = xmlProduct[i].xmlAttributes['price'];
    rtnData['products']['product_#i#']['productID'] = xmlProduct[i].xmlAttributes['productID'];
    rtnData['products']['product_#i#']['productName'] = xmlProduct[i].xmlAttributes['productName'];
    rtnData['products']['product_#i#']['quantity'] = xmlProduct[i].xmlAttributes['quantity'];
    rtnData['products']['product_#i#']['optionSubTotal'] = xmlProduct[i].xmlAttributes['optionSubTotal'];
    rtnData['products']['product_#i#']['itemTotal'] = xmlProduct[i].xmlAttributes['itemTotal'];
    if(listlen(xmlProduct[i].xmlAttributes['optionList'])){
     rtnData['products']['product_#i#']['options'] = structnew();
     for(x=1;x lte listlen(xmlProduct[i].xmlAttributes['optionList']);x=x+1){
      xmlOptions = xmlSearch(xmlDoc,"/orderData/product[@productID=#xmlProduct[i].xmlAttributes['productID']#][@optionList='#xmlProduct[i].xmlAttributes['optionList']#']/option");
      rtnData['products']['product_#i#']['options']['option_#x#'] = structnew();
      rtnData['products']['product_#i#']['options']['option_#x#']['optionID'] = xmlOptions[x].xmlAttributes['optionID'];
      rtnData['products']['product_#i#']['options']['option_#x#']['optionName'] = xmlOptions[x].xmlAttributes['optionName'];
      rtnData['products']['product_#i#']['options']['option_#x#']['optionPrice'] = xmlOptions[x].xmlAttributes['optionPrice'];
     }
    }
   }
  }
  </cfscript>
  <cfreturn rtnData>
 </cffunction>

 <cffunction name="setTotals" access="private" returntype="void" output="false" hint="Each time the totals need to be updated I handle this action">
  <cfscript>
  var i = 0;
  var x = 0;
  var xmlDoc = structnew();
  var xmlElem = arraynew(1);
  var xmlSubElem = "";
  var optionSubTotal = 0;
  var cartSubTotal = 0;
  var cartGrandTotal = 0;
  var cartShipTotal = 0;
  xmlDoc = xmlParse(getCartData());
  for(i=1;i lte arraylen(xmlDoc.xmlRoot.xmlChildren);i=i+1){
   xmlElem = xmlDoc.xmlRoot.xmlChildren[i];
   if(xmlElem.xmlName eq "product"){
    optionSubTotal = 0;
    for(x=1;x lte arraylen(xmlElem.xmlChildren);x=x+1){
     xmlSubElem = arraynew(1);
     xmlSubElem = xmlElem.xmlChildren[x];
     optionSubTotal = optionSubTotal + xmlSubElem.xmlAttributes['optionPrice'];
    }
    xmlElem.xmlAttributes['optionSubTotal'] = xmlFormat(optionSubTotal * xmlElem.xmlAttributes['quantity']);
    xmlElem.xmlAttributes['itemTotal'] = xmlFormat(xmlElem.xmlAttributes['optionSubTotal'] + xmlElem.xmlAttributes['itemSubTotal']);
    cartSubTotal = cartSubTotal + xmlElem.xmlAttributes['itemTotal'];
   }
  }
  for(i=1;i lte arraylen(xmlDoc.xmlRoot.xmlChildren);i=i+1){
   xmlElem = xmlDoc.xmlRoot.xmlChildren[i];
   if(xmlElem.xmlName eq "shipping"){
    cartShipTotal = xmlElem.xmlAttributes['cartShipTotal']; break;
   }
  }
  for(i=1;i lte arraylen(xmlDoc.xmlRoot.xmlChildren);i=i+1){
   xmlElem = xmlDoc.xmlRoot.xmlChildren[i];
   if(xmlElem.xmlName eq "totals"){
    xmlElem.xmlAttributes['cartSubTotal'] = xmlFormat(cartSubTotal);
    xmlElem.xmlAttributes['cartGrandTotal'] = xmlFormat(cartShipTotal + cartSubTotal); break;
   }
  }
  session[instance.xmlCartName] = toString(xmlDoc);
  </cfscript>
 </cffunction>
</cfcomponent>
0
 
LVL 12

Author Comment

by:pigmentarts
ID: 18068788
wow, will have a play!
0

Featured Post

Complete Microsoft Windows PC® & Mac Backup

Backup and recovery solutions to protect all your PCs & Mac– on-premises or in remote locations. Acronis backs up entire PC or Mac with patented reliable disk imaging technology and you will be able to restore workstations to a new, dissimilar hardware in minutes.

Join & Write a Comment

A web service (http://en.wikipedia.org/wiki/Web_service) is a software related technology that facilitates machine-to-machine interaction over a network. This article helps beginners in creating and consuming a web service using the ColdFusion Ma…
If you don't have the right permissions set for your WordPress location in IIS, you won't be able to perform automatic updates. Here's how to fix the problem.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now