Phase One (clicking the add to cart button)
For Opencart versions 1.5x, the add to cart button relies on the use of AJAX (Asynchronous JavaScript and XML) where on earlier versions it does not. Either way, both submit an HTTP POST with data to a Control file which in turn contacts a system file. All methods of adding to the cart session use the same function but the data could come from different areas in the View. For example: in catalog/view/theme/your_theme/template/product/category.tpl the add to cart buttons contact a function that is within catalog/view/javascript/common.js, where in catalog/view/theme/your_theme/template/product/product.tpl the function is embedded in the TPL itself. Both contact a Control Function entitled public function add() { which is located in catalog/controller/checkout/cart.php . During the add-to-cart process the Model is never used.
Before continuing on we want to reiterate that by default there are two JavaScript functions used to contact the Control , which in turn contacts the system file "which we will discuss later":
(1) The JavaScript function, function addToCart(product_id, quantity) { is used mostly, and is found in catalog/view/javascript/common.js. This is used by all of the default Opencart modules that offer Add-to-cart buttons, specifically pages that have MORE THAN ONE BUTTON. With the help of AJAX, this allows many communications with the same function by passing what are called "Arguments", instead of having a gazillion functions with different Element ID's on the same page "which would be necessary with many buttons." addToCart(ARGUMENT ONE, ARGUMENT TWO) - product_id & quantity.
(2)The JavaScript function, $('#button-cart').bind('click', function() { is used on the product details page found at the bottom of catalog/view/theme/your_theme/template/product/product.tpl. This function is for the product details page and is for ONE add-to-cart button only.
When we use the word “Control”, “Model”, and “View” we are talking about the MVC-L (the L standing for language). This article won’t be about MVC-L and what it is, but it helps to know the basics of MVC-L considering Open Cart “is” just that.

Phase Two (contacting stored procedure(s) to add to cart)
We have learned that the Add-To-Cart buttons when clicked make good use of JavaScript(with the help of AJAX) to first contact the control file, who’s function communicates with the Core Cart Function. Let’s take a closer look, starting with the JavaScript.
In catalog/view/javascript/common.js you will see the following line of code: (commented with //)
Code: Select all
function addToCart(product_id, quantity) {
quantity = typeof(quantity) != ‘undefined’ ? quantity : 1;
$.ajax({
url: ‘index.php?route=checkout/cart/add’, //URL TO CONTROL FUNCTION add()
type: ‘post’,
data: ‘product_id=’ + product_id + ‘&quantity=’ + quantity,
dataType: ‘json’,
success: function(json) {
$(‘.success, .warning, .attention, .information, .error’).remove();
if (json['redirect']) {
location = json['redirect'];
}
if (json['success']) {
$(‘#notification’).html(‘<div style=”display: none;”>’ + json['success'] + ‘<img src=”catalog/view/theme/default/image/close.png” alt=”" /></div>’);
$(‘.success’).fadeIn(‘slow’);
$(‘#cart-total’).html(json['total']);
$(‘html, body’).animate({ scrollTop: 0 }, ‘slow’);
}
}
});
}
Here is a very simplified explanation on how AJAX works with Opencart add-to-cart procedure:

In AJAX, the user sends a request that executes an action (which is a POST or a GET ) and the action’s response is shown into a layer, identified by an ID, without reloading the full page. This is why the only thing you see is the green success bar at the top. Next, in catalog/controller/checkout/cart.php you will see a function called public function add(). This is the function being called publicly by url: ‘index.php?route=checkout/cart/add’ in the Ajax. Within this function you will see this code:
Code: Select all
if (!$json) {
$this->cart->add($this->request->post['product_id'], $quantity, $option);
$json['success'] = sprintf($this->language->get(‘text_success’), $this->url->link(‘product/product’, ‘product_id=’ . $this->request->post['product_id']), $product_info['name'], $this->url->link(‘checkout/cart’));
Phase Three (adding to the cart array)
Now that we have pressed the add to cart button, contacted the control by means of using AJAX and passed validation, we must now contact the core system file found in system/library/cart.php Above you saw the call for $this->cart->add($this->request->post['product_id'], $quantity, $option); This is looking for a function that will be explained below.
Before I go on further to explain how this function works we need to discuss what has already happened LONG before you ever pressed the add to cart button. In a nutshell, all items along with their options are stored in a session variable. This session is started when you reach the store for the first time and does not die until you either close your browser (in which case it might still survive depending upon your browser settings) OR if you clean your cache, and lastly if you complete a checkout entirely. If you scroll to the top of system/library/cart.php you will see the following code:
Code: Select all
if (!isset($this->session->data['cart']) || !is_array($this->session->data['cart'])) {
$this->session->data['cart'] = array();
}
Continuing on with the ADD function. The function looks like this:
Code: Select all
public function add($product_id, $qty = 1, $option = array()) {
if (!$option) {
$key = (int)$product_id;
} else {
$key = (int)$product_id . ‘:’ . base64_encode(serialize($option));
}
if ((int)$qty && ((int)$qty > 0)) {
if (!isset($this->session->data['cart'][$key])) {
$this->session->data['cart'][$key] = (int)$qty;
} else {
$this->session->data['cart'][$key] += (int)$qty;
}
}$this->data = array();
}
Code: Select all
if (!$option) {
$key = (int)$product_id;
} else {
$key = (int)$product_id . ‘:’ . base64_encode(serialize($option));
}
And now the last part of this function:
Code: Select all
if ((int)$qty && ((int)$qty > 0)) {
if (!isset($this->session->data['cart'][$key])) {
$this->session->data['cart'][$key] = (int)$qty;
} else {
$this->session->data['cart'][$key] += (int)$qty;
}
}$this->data = array();
Code: Select all
if ((int)$qty && ((int)$qty > 0)) {
//validation that quantity is greater than 0 and correct form
if (!isset($this->session->data['cart'][$key])) {
//if the product DOESN’T exist in cart with matching properties/options. We are using the variable $key to run the check
$this->session->data['cart'][$key] = (int)$qty;
//add product to cart array (new product)
} else {
$this->session->data['cart'][$key] += (int)$qty;
//this is if product DOES exist in cart with matching properties/options //Add another of the same to change quantity. This is done by (+=)
}
}
The cart session array is now filled. It could be small or it could be VERY LARGE depending upon how many products or options you have added to those products. Displayed below is a print_r() of a cart filled with 4 items. This is so you can see what exactly is in the array. You can do this at anytime by running the following line:
Code: Select all
<?php print_r($this->session->data['cart']);?>:
Array ( [44] => 1 [47:YToxOntpOjIyNTtzOjEwOiIyMDExLTA0LTIyIjt9] => 1 [40] => 1 [30:YToxOntpOjIyNjtzOjI6IjE1Ijt9] => 1 )
Notice the KEY of each position is the product_id and serialized options array, separated by a ‘:’
Now we get to the good stuff! Just how does Open Cart use this cart array to show the cart contents to the user on the front end?
Phase Four (displaying the cart contents)
The cart contents are displayed in many places throughout the customers shopping experience. For our in depth glance in how this actually happens we are going to choose the shopping cart page found at index.php?route=checkout/cart
In catalog/controller/checkout/cart.php you will see the following code:
Code: Select all
$products = $this->cart->getProducts();
Code: Select all
public function getProducts() {
if (!$this->data) {
foreach ($this->session->data['cart'] as $key => $quantity) {
$product = explode(‘:’, $key);
$product_id = $product[0];
$stock = true;// Options
if (isset($product[1])) {
$options = unserialize(base64_decode($product[1]));
} else {
$options = array();
}
//EVERYTHING ELSE BELOW THIS WAS CUT TO SAVE SPACE IN THE THREAD
foreach ($this->session->data['cart'] as $key => $quantity) {
//loop through the entire cart array. Everything below this line will repeat itself as many times as necc.
Code: Select all
$product = explode(‘:’, $key);
$product_id = $product[0];
$stock = true;
This is being done here: $product = explode(‘:’, $key); //$product is now an array.
The first index of the array is the product_id so we declare that into a variable like this: $product_id = $product[0];
Now let’s deal with the possible options we just exploded into an array $products;
Code: Select all
// Options//If any options at all, execute code unserialize + decode. Else, declare empty array.
if (isset($product[1])) {
$options = unserialize(base64_decode($product[1]));
} else {
$options = array();
}
Code: Select all
$this->data[$key] = array(
‘key’ => $key,
‘product_id’ => $product_query->row['product_id'],
‘name’ => $product_query->row['name'],
‘model’ => $product_query->row['model'],
‘shipping’ => $product_query->row['shipping'],
‘image’ => $product_query->row['image'],
‘option’ => $option_data,
‘download’ => $download_data,
‘quantity’ => $quantity,
‘minimum’ => $product_query->row['minimum'],
‘subtract’ => $product_query->row['subtract'],
‘stock’ => $stock,
‘price’ => ($price + $option_price),
‘total’ => ($price + $option_price) * $quantity,
‘reward’ => $reward * $quantity,
‘points’ => ($product_query->row['points'] ? ($product_query->row['points'] + $option_points) * $quantity : 0),
‘tax_class_id’ => $product_query->row['tax_class_id'],
‘weight’ => ($product_query->row['weight'] + $option_weight) * $quantity,
‘weight_class_id’ => $product_query->row['weight_class_id'],
‘length’ => $product_query->row['length'],
‘width’ => $product_query->row['width'],
‘height’ => $product_query->row['height'],
‘length_class_id’ => $product_query->row['length_class_id']
Now back to catalog/controller/checkout/cart.php find this line of code:
Code: Select all
foreach ($products as $product) {
Product Options:
A few lines down you will find this code which allows us to iterate through the option array which was tucked inside the main array:
Code: Select all
$option_data = array();
foreach ($product['option'] as $option) {
Code: Select all
$this->data['products'][] = array(
‘key’ => $product['key'],
‘thumb’ => $image,
‘name’ => $product['name'],
‘model’ => $product['model'],
‘option’ => $option_data,
‘quantity’ => $product['quantity'],
‘stock’ => $product['stock'] ? true : !(!$this->config->get(‘config_stock_checkout’) || $this->config->get(‘config_stock_warning’)),
‘reward’ => ($product['reward'] ? sprintf($this->language->get(‘text_points’), $product['reward']) : ”),
‘price’ => $price,
‘total’ => $total,
‘href’ => $this->url->link(‘product/product’, ‘product_id=’ . $product['product_id']),
‘remove’ => $this->url->link(‘checkout/cart’, ‘remove=’ . $product['key'])
);
Open catalog/view/theme/your_theme/template/product/cart.tpl and find this code:
Code: Select all
<?php
foreach ($products as $product) {