The cart
The cart is the list of products a visitor is going to buy. In code it is the object $this->cart, available on the storefront. Through it an extension finds out what is in the cart and how much it costs, and can add or remove products.
Where it lives
| What | Where |
|---|---|
| The class | system/library/cart/cart.php |
| The data | Table oc_cart, one row per position |
| The cart page | index.php?route=checkout/cart |
A position is tied to the session of a guest or to the customer, so after login the cart is kept.
Reading the cart
// extension/acme_hello/catalog/controller/module/acme_hello.php, in index()
$data['cart_count'] = $this->cart->countProducts();
$data['cart_total'] = $this->currency->format($this->cart->getTotal(), $this->session->data['currency']);Print both variables in the module template. Add a product to the cart on the storefront and reload the home page — the module shows the number of items and their sum.
Positions
foreach ($this->cart->getProducts() as $product) {
$data['items'][] = [
'name' => $product['name'],
'quantity' => $product['quantity'],
'total' => $this->currency->format($product['total'], $this->session->data['currency']),
];
}Each position is an array: cart_id, product_id, quantity, the price for one unit price and for the whole position total, the chosen options. The price already takes into account options, discounts and special offers. The exact set of keys differs between releases 4.0 and 4.1 — print the array once with $this->log->write(print_r($product, true)) and look at it in the error log.
Methods
| Method | What it does |
|---|---|
add($productId, $quantity, $option) | Adds a product |
update($cartId, $quantity) | Changes the quantity of a position |
remove($cartId) | Removes a position |
clear() | Empties the cart |
getProducts() | Positions with prices and options |
countProducts() | Total number of items |
getSubTotal() | Sum without tax |
getTotal() | Sum with tax |
getWeight() | Total weight |
hasProducts() | Whether the cart is not empty |
hasShipping() | Whether any product needs delivery |
hasStock() | Whether everything is in stock |
update() and remove() take the id of the position cart_id, not the id of the product: the same product with different options is two positions.
Adding from code
$this->cart->add(42, 2);Two units of the product 42 appear in the cart. The third argument is the chosen options — an array where the key is the id of the product option and the value is the id of the chosen value.
Adding from a form
A button «Add to cart» in your template does not need your own controller. The form is sent to the core route, which checks the minimum quantity, the required options and the stock:
<form action="{{ add_to_cart }}" method="post" data-oc-toggle="ajax" data-oc-load="{{ cart }}" data-oc-target="#cart">
<input type="hidden" name="product_id" value="42">
<input type="hidden" name="quantity" value="1">
<button type="submit" class="btn btn-primary">{{ button_cart }}</button>
</form>add_to_cart is the link to checkout/cart.add, and cart is the link to common/cart.info — the block in the header that is reloaded after adding. Product forms in the core templates are built the same way.
Common mistake
$this->cart->add() is called directly for a product with required options or a minimum quantity. The library does not check anything: the position gets into the cart, and the error appears only at checkout. From code add only products you know for sure, and for a button on a page use the core route checkout/cart.add.