3 Steps Simple PHP MYSQL Shopping Cart – FREE Source Code

Welcome to a tutorial on how to create a simple PHP MYSQL shopping cart. Yes, there are a ton of shopping cart scripts out there in the world. But problem is, they are also bloated with features that people rarely use.

A basic shopping cart with PHP and MySQL requires the following components:

  1. Database tables – One for the list of products, one to record orders, one to record the ordered items.
  2. PHP library and endpoint to manage the shopping cart and orders.
  3. The HTML webpage itself.

Let us walk through how to create a skeletal shopping cart with no dependency on any frameworks in this guide – Read on!

ⓘ I have included a zip file with all the source code at the start of the tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

TABLE OF CONTENTS

Download & Notes Cart Database PHP Cart Core
HTML Page Useful Bits & Links The End

 

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

SOURCE CODE DOWNLOAD

Click here to download all the source code in a zip file – I have released it under the MIT License, so feel free to build on top of it if you want to.

 

FOLDERS

Here is a quick introduction to how the folders are being organized inside the zip file.

  • lib The shopping cart library.
  • public Public images, CSS, and Javascript.
  • sql SQL to build the database, remember to delete this folder after importing.

 

3 STEPS QUICKSTART

  1. Create a database, import sql/database.sql and sql/dummy.sql.
  2. Change the database settings in lib/core.php.
  3. Launch index.php in your browser.

If you spot a bug, please feel free to comment below. I try to answer questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

 

STEP 1) SHOPPING CART DATABASE

Let us start by establishing the foundations of the system – The database. Not to worry, there are only 3 simple tables here.

 

TABLES OVERVIEW

Table Description
products Holds the products available for sale.
orders Captures the customer’s name and email address.
orders_items The items of each order.


PRODUCTS TABLE

sql/database.sql
CREATE TABLE `products` (
  `product_id` int(11) NOT NULL,
  `product_name` varchar(255) NOT NULL,
  `product_image` varchar(255) DEFAULT NULL,
  `product_description` text,
  `product_price` decimal(10,2) NOT NULL DEFAULT '0.00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `products`
  ADD PRIMARY KEY (`product_id`),
  ADD KEY `name` (`product_name`);

ALTER TABLE `products`
  MODIFY `product_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
Field Description
product_id The product ID. Primary key, auto-increment.
product_name Name of the product. Indexed for better search performance.
product_image The image of the product, optional.
product_description The description of the product, optional.
product_price The price of the product. Defaults to 2 decimal places, feel free to change as required.

 

ORDERS TABLE

sql/database.sql
CREATE TABLE `orders` (
  `order_id` int(11) NOT NULL,
  `order_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `order_name` varchar(255) NOT NULL,
  `order_email` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `orders`
  ADD PRIMARY KEY (`order_id`),
  ADD KEY `name` (`order_name`),
  ADD KEY `email` (`order_email`),
  ADD KEY `order_date` (`order_date`);

ALTER TABLE `orders`
  MODIFY `order_id` int(11) NOT NULL AUTO_INCREMENT;
Field Description
order_id The order ID. Primary key and auto-increment.
order_date The order date. Default to the current timestamp.
order_name The customer’s name, indexed for easy search.
order_email The customer’s email address, indexed.

 

ORDER ITEMS TABLE

sql/database.sql
CREATE TABLE `orders_items` (
  `order_id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  `quantity` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `orders_items`
  ADD PRIMARY KEY (`order_id`,`product_id`);
Field Description
order_id The order ID. Partial primary key and foreign key.
product_id The product ID. Partial primary key and foreign key.
quantity The number of products ordered.

 

 

STEP 2) PHP SHOPPING CART CORE

Now that we have established the database foundations, let us move on to build the PHP shopping cart.

 

PHP CART CORE LIBRARY

THE CORE FUNCTIONS

lib/core.php
<?php
class CartCore {
  // (A) CORE FUNCTIONS
  // (A1) PROPERTIES
  public $pdo = null;
  public $stmt = null;
  public $error = "";

  // (A2) CONSTRUCTOR - CONNECT TO DATABASE
  function __construct() {
    try {
      $this->pdo = new PDO(
        "mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=".DB_CHARSET,
        DB_USER, DB_PASSWORD, [
          PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]
      );
    } catch (Exception $ex) { exit($ex->getMessage()); }
  }

  // (A3) DESTRUCTOR - CLOSE DATABASE CONNECTION
  function __destruct() {
    if ($this->stmt !== null) { $this->stmt = null; }
    if ($this->pdo !== null) { $this->pdo = null; }
  }

  // (A4) HELPER FUNCTION - EXECUTE SQL QUERY
  function query ($sql, $data=null) {
    try {
      $this->stmt = $this->pdo->prepare($sql);
      $this->stmt->execute($data);
      return true;
    } catch (Exception $ex) {
      $this->error = $ex->getMessage();
      return false;
    }
  }
} 

The class CartCore pretty much contains all the mechanics of the shopping cart, and this first section should be pretty self-explanatory.

  • A1 – $pdo and $stmt are used to contain the PDO object, $error to hold any error messages.
  • A2 & A3 – When a new CartCore() object is created, the constructor will automatically connect to the database, the destructor will close the connection.
  • A4 – query() is just a helper function to run SQL queries.

 

PRODUCT FUNCTIONS

lib/core.php
// (B) PRODUCT FUNCTIONS
// (B1) GET ALL PRODUCTS
function pdtGetAll () {
  $this->query("SELECT * FROM `products`");
  $pdts = [];
  while ($row = $this->stmt->fetch()) { $pdts[$row['product_id']] = $row; }
  return count($pdts)==0 ? null : $pdts ;
}
 
// (B2) GET PRODUCT
function pdtGet ($id) {
  $this->query("SELECT * FROM `products` WHERE `product_id`=?", [$id]);
  return $this->stmt->fetch();
}

Don’t think these need explanation, just products-related SQL.

  • B1 – pdtGetAll() get all products from the database.
  • B2 – pdtGet() get specified product ID.

 

 

SHOPPING CART FUNCTIONS

lib/core.php
// (C) CART FUNCTIONS
// (C1) UPDATE ITEM IN CART
function cartItem ($id, $qty, $add=true) {
  // CHECK ID AND QTY
  if (!is_numeric($id) || !is_numeric($qty)) {
    $this->error = "Invalid product ID or quantity";
    return flase;
  }

  // REMOVE ITEM
  if ($qty==0) { unset($_SESSION['cart'][$id]); }

  // ADD ITEM TO CART
  else if ($add) {
    if (is_numeric($_SESSION['cart'][$id])) { $_SESSION['cart'][$id] += $qty; }
    else { $_SESSION['cart'][$id] = $qty;  }
  }

  // SET TO EXACT QUANTITY
  else { $_SESSION['cart'][$id] = $qty; }

  // OVER MAX
  if ($_SESSION['cart'][$id] > CART_MAX) { $_SESSION['cart'][$id] = CART_MAX; }

  return true;
}

// (C2) COUNT ITEMS IN CART
function cartCount () {
  $total = 0;
  if (count($_SESSION['cart'])>0) {
    foreach ($_SESSION['cart'] as $id => $qty) { $total += $qty; }
  }
  return $total;
}

// (C3) GET ALL ITEMS IN CART
function cartGetAll () {
  // CART EMPTY
  if (count($_SESSION['cart'])==0) { return false; }

  // GET PRODUCTS IN CART
  $sql = "SELECT * FROM `products` WHERE `product_id` IN (";
  $sql .= str_repeat('?,', count($_SESSION['cart']) - 1) . '?';
  $sql .= ")";
  $this->query($sql, array_keys($_SESSION['cart']));
  $pdts = [];
  while ($row = $this->stmt->fetch()) { $pdts[$row['product_id']] = $row; }
  return count($pdts)==0 ? null : $pdts ;
}

// (C4) CHECKOUT
function cartCheckout ($name, $email) {
  // AUTO COMMIT OFF
  $this->pdo->beginTransaction();

  // CREATE NEW ORDER
  $pass = $this->query(
    "INSERT INTO `orders` (`order_name`, `order_email`) VALUES (?, ?)",
    [$name, $email]
  );

  // INSERT THE ITEMS
  if ($pass) {
    $this->orderID = $this->pdo->lastInsertId();
    $sql = "INSERT INTO `orders_items` (`order_id`, `product_id`, `quantity`) VALUES ";
    $cond = [];
    foreach ($_SESSION['cart'] as $id=>$qty) {
      $sql .= "(?, ?, ?),";
      array_push($cond, $this->orderID, $id, $qty);
    }
    $sql = substr($sql, 0, -1) . ";";
    $pass = $this->query($sql, $cond);
  }

  // FINALIZE
  if ($pass) { 
    $this->pdo->commit(); 
    $_SESSION['cart'] = [];
  } else { $this->pdo->rollBack(); }

  // SEND EMAIL
  if ($pass) { if (!$this->emailOrder($this->orderID)) {
    $this->error = "Order saved, but error sending mail";
  }}

  return $pass;
}

// (C5) EMAIL ORDER TO CUSTOMER
function emailOrder ($id) {
  // GET ORDER
  $this->query("SELECT * FROM `orders` WHERE `order_id`=?", [$id]);
  $order = $this->stmt->fetch();
  if (!is_array($order)) {
    $this->error = "Invalid order";
    return false;
  }

  // GET ITEMS
  $this->query("SELECT * FROM `orders_items` LEFT JOIN `products` USING (`product_id`) WHERE `orders_items`.order_id=?", [$id]);
  $order['items'] = [];
  while ($row = $this->stmt->fetch()) { $order['items'][$row['product_id']] = $row; }

  // FORMAT EMAIL - CHANGE AS YOU SEE FIT
  $mailTo = $order['order_email'];
  $mailSubject = "Order Received";
  $mailBody = "Dear " . $order['order_name'] . ",<br>";
  $mailBody .= "Thank you and we have received your order.<br>";
  foreach ($order['items'] as $pid=>$p) {
    $mailBody .= $p['product_name'] . " - " . $p['quantity'] . "<br>";
  }
  $mailHead = implode("\r\n", [
    'MIME-Version: 1.0',
    'Content-type: text/html; charset=utf-8'
  ]);

  // SEND EMAIL
  if (@mail($mailTo, $mailSubject, $mailBody, $mailHead)) {
    return true;
  } else {
    $this->error = "Error sending email";
    return false;
  }
}

The shopping cart is the biggest chunk and looks massive. But keep calm and study slowly:

  • C1 – Items in the cart will be kept in the session, in the format of $_SESSION['cart'][PRODUCT ID] = QUANTITY. All cartItem() does is to update the quantities in the session, that’s all.
  • C2 – cartCount() Counts the total number of items in the cart. Easy.
  • C3 – cartGetAll() Gets the details of the items in the cart.
  • C4 & C5 – cartCheckout() Checkout the current cart,  emailOrder() send the order via email.

 

SETTINGS & INIT

lib/core.php
// (D) SETTINGS
// (D1) DATABASE - CHANGE TO YOUR OWN!
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_CHARSET', 'utf8');
define('DB_USER', 'root');
define('DB_PASSWORD', '');

// (D2) ERROR REPORTING
error_reporting(E_ALL & ~E_NOTICE);

// (D3) PATH
define('PATH_LIB', __DIR__ . DIRECTORY_SEPARATOR);

// (D4) CART SETTINGS
define('CART_MAX', 99);

// (E) START!
session_start();
if (!is_array($_SESSION['cart'])) { $_SESSION['cart'] = []; }
$_CC = new CartCore();
  • D – Finally, this section contains some settings. Remember to change the database to your own.
  • E – Starts the session, create a $_CC = new CartCore() object to start the engine.

 

AJAX HANDLER

ajax-cart.php
<?php
// (A) INIT
require "lib/core.php";
switch ($_POST['req']) {
  // (B) INVALID REQUEST
  default:
    echo "INVALID REQUEST";
    break;

  // (C) ADD ITEM TO CART
  case "add":
    $pass = $_CC->cartItem($_POST['product_id'], 1);
    echo json_encode([
      "status" => $pass,
      "message" => $pass ? "Item added to cart" : $_CC->error
    ]);
    break;

  // (D) CHANGE QTY
  case "change":
    $pass = $_CC->cartItem($_POST['product_id'], $_POST['qty'], false);
    echo json_encode([
      "status" => $pass,
      "message" => $pass ? "Quantity updated" : $_CC->error
    ]);
    break;

  // (E) COUNT TOTAL NUMBER OF ITEMS
  case "count":
    echo $_CC->cartCount();
    break;

  // (F) SHOW CART ITEMS
  case "show":
    $products = $_CC->cartGetAll();
    $sub = 0; $total = 0; ?>
    <h1>MY CART</h1>
    <table id="scTable">
      <tr>
        <th>Remove</th> <th>Qty</th> <th>Item</th> <th>Price</th>
      </tr>
      <?php
      if (count($_SESSION['cart'])>0) { foreach ($_SESSION['cart'] as $id => $qty) {
      $sub = $qty * $products[$id]['product_price'];
      $total += $sub; ?>
      <tr>
        <td>
          <input class="scDel bRed" type="button" value="X" onclick="cart.remove(<?= $id ?>);"/>
        </td>
        <td><input id='qty_<?= $id ?>' onchange='cart.change(<?= $id ?>);' type='number' value='<?= $qty ?>'/></td>
        <td><?= $products[$id]['product_name'] ?></td>
        <td><?= sprintf("$%0.2f", $sub) ?></td>
      </tr>
      <?php }} else { ?>
      <tr><td colspan="3">Cart is empty</td></tr>
      <?php } ?>
      <tr>
        <td colspan="2"></td>
        <td><strong>Grand Total</strong></td>
        <td><strong><?= sprintf("$%0.2f", $total) ?></strong></td>
      </tr>
    </table>
    <?php if (count($_SESSION['cart']) > 0) { ?>
    <form id="scCheckout" onsubmit="return cart.checkout();">
      <h1>CHECKOUT</h1>
      <label>Name</label>
      <input type="text" id="co_name" required value="John Doe"/>
      <label>Email</label>
      <input type="email" id="co_email" required value="john@doe.com"/>
      <input type="submit" class="bRed" value="Go"/>
    </form>
    <?php }
    break;

  // (G) CHECKOUT - DO YOUR SECURITY CHECKS + PAYMENT HERE!
  case "checkout":
    $pass = $_CC->cartCheckout($_POST['name'], $_POST['email']);
    echo json_encode([
      "status" => $pass,
      "message" => $pass ? "Order confirmed" : $_CC->error
    ]);
    break;
}

Of course, the Stone Age of the Internet is long over… The application will be AJAX-driven, and how it works is dreadfully simple. Just send the respective request $_POST['req'] followed by the required parameters.

Req Description
add Add a new item to the cart.

Parameters: product_id

change Change the quantity of an item in the cart. A quantity of 0 will remove the product from the cart.

Parameters: product_id, qty

count Get the total number of items in the cart.
show Show the current shopping cart.
checkout Check out the current cart.

Parameters: name, email

 

 

STEP 3) HTML SHOPPING PAGE

Now that we have established the necessary system groundworks, all that’s left is the HTML shopping page.

 

THE PRODUCTS PAGE

index.php
<!-- (A) HEADER -->
<header id="scHead">
  <div id="scTitle">MY SHOP</div>
  <div id="scCartIcon" onclick="cart.toggle();">
    &#128722; <span id="scCartCount">0</span>
  </div>
</header>
 
<!-- (B) PRODUCTS --> 
<div id="scProduct"><?php
  // (B1) GET PRODUCTS
  require "lib/core.php";
  $products = $_CC->pdtGetAll();
 
  // (B2) LIST PRODUCTS
  if (is_array($products)) { foreach ($products as $id => $row) { ?>
  <div class="pdt">
    <img class="pImg" src="public/<?= $row['product_image'] ?>"/>
    <h3 class="pName"><?= $row['product_name'] ?></h3>
    <div class="pPrice">$<?= $row['product_price'] ?></div>
    <div class="pDesc"><?= $row['product_description'] ?></div>
    <input class="pAdd bRed" type="button" value="Add to cart" onclick="cart.add(<?= $row['product_id'] ?>);"/>
  </div>
  <?php }} else { echo "No products found."; }
?></div>
 
<!-- (C) CART -->
<div id="scCart" class="ninja"></div>
  • A – Header and “show cart” button.
  • B – List of products.
  • C – Current cart items, hidden by default. We will use Javascript to load and toggle it.

Of course, feel free to change the structure of this page as you see fit.

 

THE CSS

public/cart.css
/* (A) ENTIRE PAGE */
html, body {
  font-family: arial, sans-serif;
  max-width: 1200px;
  padding: 0;
  margin: 0 auto;
}
.bRed {
  background: #c13e3e;
  font-size: 1.1em;
  color: #fff;
  border: 0;
  padding: 10px;
  cursor: pointer;
}
.ninja { display: none !important; }

/* (B) HEADER */
#scHead {
  position: sticky;
  top: 0;
  display: grid;
  grid-template-columns: auto 100px;
  color: #fff;
  background: #353535;
  font-size: 1.4em;
}
#scTitle, #scCartIcon { padding: 20px; }
#scCartIcon {
  background: #565656;
  text-align: center;
  cursor: pointer;
}
#scCartIcon.active { background: #c13e3e; }

/* (C) PRODUCTS LIST */
#scProduct {
  display: grid;
  grid-template-columns: auto auto auto;
  grid-gap: 10px;
  padding: 10px;
}
@media all and (max-width: 768px) {
  #scProduct { grid-template-columns: auto auto; }
}
.pdt {
  background: #f0f0f0;
  padding: 10px;
}
.pImg {
  max-width: 100%;
  object-fit: contain;
}
.pName {
  margin: 5px 0;
  color: #0e0e0e;
}
.pPrice { color: #a82828; }
.pDesc { color: #777; }
.pAdd {
  width: 100%;
  margin-top: 10px;
}

/* (D) SHOPPING CART */
#scCart { padding: 10px; }
#scTable {
  border-collapse: collapse;
  width: 100%;
}
#scTable th { text-align: left; }
#scTable th, #scTable td { padding: 10px; }
#scTable tr:nth-child(odd) { background: #f2f2f2; }
#scTable input[type=number] {
  width: 60px;
  padding: 5px;
}

/* (E) CHECKOUT FORM */
#scCheckout {
  margin-top: 10px;
  max-width: 320px;
}
#scCheckout input {
  box-sizing: border-box;
  padding: 5px;
  margin: 5px;
  width: 100%;
}

Holy cow! That is a lot of CSS code, but ultimately, just some cosmetics. Feel free to change the styles to fit your own website’s theme.

 

 

SHOPPING CART JAVASCRIPT

public/cart.js
var cart = {
  // (A) HELPER FUNCTION - AJAX CALL
  // opt.data : data to be sent, an object with key-value pairs
  // opt.target : (optional) ID of HTML element, put server response in here if provided
  // opt.done : (optional) function to call when AJAX load is complete
  ajax : function (opt) {
    // (A1) DATA
    var data = null;
    if (opt.data) {
      data = new FormData();
      for (var d in opt.data) { data.append(d, opt.data[d]); }
    }

    // (A2) AJAX
    var xhr = new XMLHttpRequest();
    xhr.open('POST', "ajax-cart.php");
    xhr.onload = function(){
      if (xhr.status!=200) {
        alert("Server responded with error code " + xhr.status + " " + xhr.statusText);
      } else {
        if (opt.target) { document.getElementById(opt.target).innerHTML = this.response; }
        if (typeof opt.done == "function") { 
          try { var res = JSON.parse(this.response); }
          catch (err) { var res = null; }
          if (res===null) { opt.done(); }
          else { opt.done((res)); }
        }
      }
    };
    xhr.send(data);
  },

  // (B) ADD ITEM TO CART
  add : function (id) {
    cart.ajax({
      data : {
        req : "add",
        product_id : id
      },
      done: function (res) {
        if (res.status == true) {
          cart.count(); 
          alert("Item added");
        } else { alert(res.message); }
      }
    });
  },

  // (C) UPDATE ITEMS COUNT
  count : function () {
    cart.ajax({
      data : { req : "count" },
      target : "scCartCount"
    });
  },

  // (D) SHOW/HIDE CART
  toggle : function (reload) {
    // (D1) GET HTML ELEMENTS
    var pgIco = document.getElementById("scCartIcon"),
        pgPdt = document.getElementById("scProduct"),
        pgCart = document.getElementById("scCart");

    // (D2) LOAD CART
    if (reload || pgCart.classList.contains("ninja")) {
      cart.ajax({
        data : { req : "show" },
        target : "scCart",
        load : function () {
          pgIco.classList.add("active");
          pgPdt.classList.add("ninja");
          pgCart.classList.remove("ninja");
        }
      });
    } else {
      pgIco.classList.remove("active");
      pgPdt.classList.remove("ninja");
      pgCart.classList.add("ninja");
    }
  },

  // (E) CHANGE ITEM QUANTITY
  change : function (id) {
    var qty = document.getElementById("qty_"+id).value;
    cart.ajax({
      data : {
        req : "change",
        product_id : id,
        qty : qty
      },
      load : function (res) {
        cart.count();
        cart.toggle(1);
        alert(res.message);
      }
    });
  },

  // (F) REMOVE ITEM FROM CART
  remove : function (id) {
    document.getElementById("qty_"+id).value = 0;
    cart.change(id);
  },

  // (G) CHECKOUT
  checkout : function () {
    cart.ajax({
      data : {
        req : "checkout",
        name : document.getElementById("co_name").value,
        email : document.getElementById("co_email").value
      },
      load : function (res) {
        cart.count();
        cart.toggle(1);
        alert(res.message);
        // if (res.status) { location.href = "THANK-YOU-PAGE"; }
      }
    });
    return false;
  }
};
window.addEventListener("DOMContentLoaded", cart.count);

Yep, this Javascript will pretty much do most of the shopping cart magic on the HTML page. It may seem pretty complicated, but it is actually nothing more than a bunch of AJAX calls to the server.

Function Description
cart.ajax Helper function, does an AJAX call.
cart.add Add an item to the cart.
cart.count Update the total number of items in the cart.
cart.toggle Show/hide the shopping cart contents.
cart.change Change the quantity of an item in the cart.
cart.remove Remove an item from the cart.
cart.checkout Check out the current order.

 

USEFUL BITS & LINKS

That’s all for this project, and here is a small section on some extras that may be useful to you.

 

ADDING MORE FIELDS

Need to capture more fields? Well, there are 3 parts to the system, and you just need to modify them accordingly:

  • Database – Add your required fields to the tables accordingly.
  • Server-side scripts – Update the AJAX handler ajax-cart.php and PHP library lib/core.php to properly capture the additional fields.
  • Client-side scripts – Include the new field in the product page index.php and the Javascript public/cart.js.

 

FUTURE EXPANSIONS & MORE TUTORIALS

This tutorial has barely covered a small part of a possibly massive system. It is still missing a user system, an administrator’s panel, and so much more. Here are a few links to my other guides that may be useful:

Or consider getting my eBook below.

 

A BETTER SHOPPING CART

Need a shopping cart with product options? Product categories? Discount coupons? User system and admin panel? Click here to check out my eBook! Go ahead, take a sneak peek inside - Click here to download the first 4 chapters.

 

FULL-FLEDGED SHOPPING CARTS

Changed your mind? Don’t want to do so much coding? Try:

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

54 thoughts on “3 Steps Simple PHP MYSQL Shopping Cart – FREE Source Code”

  1. * What if I want the product name and subtotal to be inserted into the db tho?
    * Hey if I wanted to insert product name into the order item db, where do i need to alter?
    * I’ve got a uncaught error: call to a member function getAll() on null when i used $_CC->Cart->getAll() in lib-cart.php
    * Where do you have to use $_CC->Cart->getAll()? I received a fatal error that traced back to ajax-cart.php(100): Cart->checkout(‘John Doe’, ‘john@doe.com’)

Leave a Comment

Your email address will not be published. Required fields are marked *