I was trying to troubleshoot an issue with quotes in Magento 1.x the other day and did some digging through the core code. I now have a much better understanding of what the process looks like when a quote is written to the sales_flat_quote
table. The process is a bit complex and has some unique items to it that I didn’t expect to see. For that reason I thought I’d document the process in clear English in the hopes that it helps someone else better understand the process as well.
Contents
Unique Findings
- The customer information (
customer_id
,customer_email
,customer_firstname
, etc.) are not written to the quote when the quote is generated - The
customer_id
only is updated on the table every time the quote is saved.
Updating a Quote vs Creating a New Quote
A new customer would obviously create a new quote record in the sales_flat_quote
table as there wouldn’t be a record for that customer.
Additionally, after a quote is converted to an order (after checkout success) the quote has a column is_active
that is modified from 1 (active) to 0 (inactive/converted to an order). At this time, it’s as if the customer is new again, and a new quote will be added to the sales_flat_quote
table with the next add to cart action.
When the Customer Information Is Added to the Quote
The default Magento add to cart method, Mage_Checkout_CartController -> addAction
writes the quote to sales_flat_quote
. What I find interesting though is that Magento does not set the customer information (customer_id
, customer_email
, etc) on this record in sales_flat_quote
at this time. Those values are set to NULL
. If the customer has an active quote in the table already, the table will of course not have NULL
for the customer information fields as they were already set. The customer information fields will however be set to the table the next time that the quote is saved.
The default Magento add to cart method redirects the customer to the cart page (www.yourdomain.com/checkout/cart/
) after the add to cart process is complete. At this time, the cart is updated and thus the customer information will be set, obtaining this information from the checkout/session
singleton.
A Walk Through the Core Code
The cart controller, Mage_Checkout_CartController -> indexAction
then loads the quote. This action calls:
1 2 3 4 5 6 7 8 9 10 |
$cart = $this->_getCart(); /** * Retrieve shopping cart model object * * @return Mage_Checkout_Model_Cart */ protected function _getCart() { return Mage::getSingleton('checkout/cart'); } |
This gets the cart from the singleton Mage_Checkout_Model_Cart
. The init()
method calls the getQuote()
method:
1 2 3 4 5 6 7 8 9 10 11 |
/** * Initialize cart quote state to be able use it on cart page * * @return Mage_Checkout_Model_Cart */ public function init() { $quote = $this->getQuote()->setCheckoutMethod(''); ..... return $this; } |
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * Get quote object associated with cart. By default it is current customer session quote * * @return Mage_Sales_Model_Quote */ public function getQuote() { if (!$this->hasData('quote')) { $this->setData('quote', $this->getCheckoutSession()->getQuote()); } return $this->_getData('quote'); } |
This then calls the getCheckoutSession()
method which loads the customer information from the checkout/session
singleton.
1 2 3 4 5 6 7 8 9 |
/** * Retrieve checkout session model * * @return Mage_Checkout_Model_Session */ public function getCheckoutSession() { return Mage::getSingleton('checkout/session'); } |
That whole chain of commands finally sets the customer information to the quote object $cart
in the cart controller, Mage_Checkout_CartController -> indexAction
and eventually gets saved to the sales_flat_quote
table when the Mage_Checkout_CartController -> indexAction
calls:
1 |
$cart->save(); |
That long explanation shows how the customer information finally makes it to the sales_flat_quote
table when the default Magento method is used.
There is one additional piece of complexity to this process. Every time a quote is saved (add to cart, view cart page, every step in the checkout process) the customer_id
only will be updated by Mage_Sales_Model_Quote -> _beforeSave()
.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * Prepare data before save * * @return Mage_Sales_Model_Quote */ protected function _beforeSave() { .... if ($this->_customer) { $this->setCustomerId($this->_customer->getId()); } parent::_beforeSave(); } |
Looking closer at how the quote is loaded, Mage_Checkout_Model_Cart -> getQuote()
calls:
1 |
$this->getCheckoutSession()->getQuote() |
The getCheckoutSession
method loads from the checkout/session
singleton:
1 2 3 4 5 6 7 8 9 |
/** * Retrieve checkout session model * * @return Mage_Checkout_Model_Session */ public function getCheckoutSession() { return Mage::getSingleton('checkout/session'); } |