Search

Hey guys, I was wondering how you guys build out ecommerce functionality. I’m guessing you use Storage to store values, but how do you calculate the price of an order?

I was thinking of using Reflection field, but the problem is that Select Box Link fields (linking to the items) won’t provide the necessary entry info in the XML (price, discounts, etc.). I don’t want to calculate prices in XSL and pass it through inputs b/c the user could obviously hack that. Any suggestions?

@Pat never completly built one, though I had a draft. I had built the 'view' values using XSLT as you describe; however I never passed any monetary values just amounts of each object. I did however use the event (customized if not mistaken) to re-calculate the amount (in php) before showing a confirmation/payment page.

I got 90% of the way through one before the client pulled the plug, and yes Storage was in testing on that site and worked very well for basket and wishlist features.

I had the xslt calculate the prices based on the values and quantities in Storage, and as Jonathan did, I had the PHP calculate the prices and totals again for adding to the sections.

As John mentioned, I've also used storage on a small Merch site which passes off totals and discounts to Paypal for calculation.

Customer checks order manually for price accuracy.. (That's how they wanted to deal with it).

Have also integrated/passed payments over to Formstack.com forms which then use web hooks to post back to a symphony section for successful payments.

Why would you need to save the total price back into the system? It's just a matter of adding or multiplying numbers.

But even worse you will need to save the complete order, i.e numbers of items with their current prices at the time of ordering. (Prices may change, and shop items may be removed, so just linking to items in another section doesn't work.)

In a very small shop I serialized the basket (Storage) in XSLT and saved it into a textarea field using a hidden field in the form. But that can be manipulated, of course. It's only usful if the total number of shop items is small, so the people who care for the orders know the prices by heart.

It would of course be better to use a customized event resp. event filter, as @gunglien said.

We are using a hidden textarea to store the baskets as well. We then output the saved markup in the XML and adjust (simplify) it using the ninja technique when sending out confirmation emails. As Michael pointed out, this makes sure that you have a snapshot of the order at the time of ordering.

If you want to make this more secure, you would have to recreate and recalculate the basket in a custom event using the amount from Storage and the prices from Symphony. But storing the basket as XML turned out quite foolproof so far.

For the order system I did there weren't discounts and complicated things to take into account, so for the basket view I calculated in XSLT.

For order placement, I took the product ids and quantities from the $_POST and calculated in PHP via a custom 'save_order' event. For saving placed orders, I saved the product list (SKUs, quantity, name, variant, etc.) into a Dynamic Text Group field. This also had the side effect of allowing the shop owner to update the order's line items in placed orders.

I suppose in your case you'll also need a custom event for the basket for the calculations.

If you have fairly complicated requirements (and e-commerce can easily get very complicated with regional taxes, delivery, etc.), it might also be worth looking at FoxyCart.

For saving placed orders, I saved the product list (SKUs, quantity, name, variant, etc.) into a Dynamic Text Group field. This also had the side effect of allowing the shop owner to update the order's line items in placed orders.

Looking at Brendan's Metakeys field might be interesting in this context as well.

Wow so many responses!

@gunglien, @designermonkey: When calculating prices in PHP (event I assume), did you fetch the prices from another Symphony entry?

@michael-e: Thanks, I was concerned about price changes, so it makes sense that a Reflection-ized value would not be a good choice. Saving the total price would just be nice to sort by large orders and such.

@Michael & Nils: Are you guys are outputting XML in a textarea hidden on the page? Or are you using a custom event to serialize the basket and insert it before the entry is saved? What kind of data do you save?

  • product entry id
  • price
  • amount
  • anything else?

Yes, it's a hidden field. But in order to save the content to the textarea, I had to serialize the XHTML (which makes the "basket" on the page). For that task, I used the XML serializer by Evan Lenz.

However, I encourage you to follow Nils' suggestion and look into Meta Keys. It should make it possible to save the POSTed data in a much better way.

To say this more clearly: Nils' method of saving into a textarea (which I actually stole from him) is only useful for small shops. Orders will not be editable by authors. In my case it was only necessary to send emails, and so saving orders' XML was just a "developer's fallback" in case anything goes wrong.

@Pat if not mistaken yes I had fetched some data. I can double check this evening/tomorrow when I get access to the draft I had on my home machine.

I'd also reccomend keeping the values stored as mentioned. Unless you have a complex structure of storing the prices. That is a base-price and offer-prices, which vary according to the date(s).

I had opted to set a base-price. And then when required a new price would be added for the product (available from that day onwards, until another offer is placed or till it expires) in case of expiry drops back to the base-price. So this way I could always use one of these values to get the original price at date of purchase. Storing the actual value at time of purchase would however make it fool-proof.

@michael: I’m not sure how Meta Keys would work, as the key value pairs wouldn't be grouped (saving the ID, price and value for multiple products).

@gunglien: Do you copy the prices from each product in your “orders” section? I think that’s the only way to store the price at the time of purchase.

You would probably have to link "ordered items" to "orders" using SBL. That would also mean saving to both sections at the same time.

Would it be easier using the Dynamic Text Group field? (I never tried that field, but I didn't have the impression that the extension is supported very well, so I opted for the Meta Keys idea.)

Speaking of Reflection field (RF) and value changes, would it make sense to be able to take into account the last known value of RF in its custom XSLT utility evaluation feature?

So lets say I could decide in a XSLT condition, if I want to keep the former value, or to update it, for example when another field's value would say so (e.g. a checkbox field "Do Update the Receipt" - this would be opted out for the initial frontend event).

@Michael: So would meta keys just store the quantity of each product? I also am not sure about Dynamic Text Group (latest comment doesn’t sound good)

@juro: I do believe that works. You can access the value of the reflection field, in the reflection field XSLT utility. I think an xsl:choose would work just fine.

Worst case scenario, I store product quantities as XML in a text field. The one thing I’m not sure of is how to pass the prices securely. I wouldn’t want to do this on the page, so I’m guessing I need an event that looks up prices based on SBL ids for the “ordered items” field, then stores them in the order.

Meta Keys can store multiple key/value pairs, so you might store the quantity, the price, a "variant", whatever. You might try to have two fields in the "ordered items" section:

  • SBL (linked to the order)
  • Meta Keys

@michael: ah, I go tit. You mean have separate sections like this:

  • products
  • orders
    • Total calculated in PHP/event
  • ordered items
    • SBL linked to order
    • meta keys for quantity, price, color, etc.
    • SBL linked to product

I actually figured out how to get the prices with an event. Something like this

public function findValueFromEntryId($data, $field_id) {
    $entry = Symphony::Database()->fetchRow(0, sprintf("
            SELECT `value` FROM `sym_entries_data_%d`
            WHERE `entry_id` = '%s'
            LIMIT 1",
        $field_id, addslashes($data)
    ));

    return $entry['value'];
}

You mean have separate sections like this:

Yep, exactly. In the backend you might use the HTML Panel Field extension to show all ordered items for an orders entry (on the edit page).

EDIT: The new Associations interface might do the job as well.

I never thought about retaining a text value of the products ordered. If I were to do that, I would use the XML field to store an XML representation of it, not try and serialise the data.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details