PHP Shopping Cart Tutorial – Step By Step Guide!
Previously, we learned how to create, read, update and delete database records on our PHP OOP CRUD tutorial. Today, we will put that knowledge to work by building a simple PHP shopping cart application.
This post will have the following contents:
1.0 Overview
2.0 Source code output preview
3.0 File structure
4.0 Prepare the database
4.1 Database design
4.2 Create MySQL tables
4.3 Database connection file
4.4 Output
5.0 Prepare the user interface
5.1 Create header layout file
5.2 Create footer layout file
5.3 Create navigation.php
5.4 Add custom CSS
5.5 Output
6.0 Display products
6.1 Create products.php
6.2 Include PHP classes
6.3 Create "product" object file
6.4 Create "product image" object file
6.5 Create "cart item" object file
6.6 Connect to the database
6.7 Initialize action and pagination
6.8 Request data from the database
6.9 Add "read" and "count" methods
6.10 Template to display products
6.11 Add "readFirst()" method
6.12 Add "exists()" method
6.13 Create pagination file
6.14 Output
7.0 How to count items in the cart?
7.1 Display count in navigation bar
7.2 Cart item count() method
7.3 Output
8.0 How to add to cart?
8.1 Make "add to cart" button work
8.2 Create add_to_cart.php
8.3 Put create() method
8.4 Create cart.php
8.5 Display message based on action
8.6 Display cart items
8.7 Put read() method in cart item object
8.8 Read products by IDs
8.9 Output
9.0 How to update cart?
9.1 Update cart quantity with JavaScript
9.2 PHP script to update cart
9.3 Update cart item in database
9.4 How to remove product from cart?
9.5 Put delete() method
9.6 Create the checkout page
9.7 Create place_order.php
9.8 Delete all items in the cart
9.9 Output
10.0 How to make the product page?
10.1 Create product.php
10.2 Read product details
10.3 Read one product method
10.4 Display message based on action
10.5 Display product thumbnails
10.6 Read images related to product
10.7 Display product image
10.8 Make image hover work
10.9 Display product details
10.10 Render 'Cart' button
10.11 Output
11.0 What People Say About This Code?
12.0 Download the LEVEL 1 Source Code
13.0 Download the LEVEL 2 Source Code
14.0 Download the PHP Shopping Cart Module
15.0 Download the PHP Shopping Cart SYSTEM
16.0 What's Next?
17.0 Related Tutorials
18.0 Notes
Before we start, we want to let you know that your feedback is important to us!
If you have a positive feedback about our work, please let us know. If there's a section in this tutorial that is confusing or hard to understand, we consider it as a problem. Please let us know as well.
Write your positive feedback or detailed description of the problem in the comments section below. Before you write a comment, please read this guide and our code of conduct. Thank you!
1.0 Overview
This is good news for you. If you do not want to use cookies or sessions for storing cart items, you can use your MySQL or MariaDB database.
Will there be any advantage if we use this approach?
One advantage I can think of is, the user can view his cart items in different computers or devices.
If we will compare it to using PHP sessions or cookies, we can say the following:
- PHP sessions can maintains the cart items only when the browser is opened. It means a user will lose his cart items once he closes his browser or turns off his computer.
- PHP cookies can maintain the cart items on one device or computer, event if the user turn his computer on and off.
The source codes in this page is NOT for you if:
- You are an already an expert in PHP & MySQL programming.
- You have a lot of time to code a shopping cart system from scratch.
- You are not that interested in learning PHP & MySQL programming.
But, this SOURCE CODE is FOR YOU if:
- You want to SAVE huge amount of development time.
- You want to develop your own shopping cart system from scratch.
- You determined to learn how to make a web application in PHP & MySQL.
But if you are an expert in PHP & MySQL programming and would like to take a look at our code, please do so! We'd love to hear your response and great insights! The comments section below is always open for anyone with questions and suggestions.
2.0 Source Code Output Preview
Below are some screenshots of our script’s output. You can click an image to view the larger version of it. Use the left and right arrow to navigate through the screenshots.
Please note that the following images are just output previews. New features might be added already the time you are reading this.
Note: If the output preview is in video format, please click the play button instead.
2.1 LEVEL 1 Source Code Output
2.2 LEVEL 2 Source Code Output
2.3 PHP Shopping Cart Module Output
The LEVEL 2 and PHP Shopping Cart Module outputs proves that you can add and customize more features. It's easier and faster if you will learn by following our tutorial below.
Downloading our source codes is your huge advantage as well. For now, let's proceed to the step by step tutorial of our LEVEL 1 source code. Enjoy!
3.0 File Structure
The following folders and files are included in the source code. It will have more meaning if you will see the code inside the folders and files.
├─ config/
├─── database.php
├─ dev/
├─── shop_cart_mysql_1.sql
├─── readme.txt
├─ images/
├─ libs/
├─── css/
├────── bootstrap/
├─── js/
├────── jquery.js
├─ objects/
├─── cart_item.php
├─── product_image.php
├─── product.php
├─ uploads/
├─── images/
├─ .htaccess
├─ add_to_cart.php
├─ cart.php
├─ checkout.php
├─ layout_foot.php
├─ layout_head.php
├─ navigation.php
├─ paging.php
├─ place_order.php
├─ product.php
├─ products.php
├─ read_products_template.php
├─ remove_from_cart.php
├─ update_quantity.php
4.0 Prepare the database
4.1 Database Design
Our database name is "shop_cart_mysql_1", and we will have three (3) tables.
4.2 Create MySQL Tables
You may run the following SQL queries on our "shop_cart_mysql_1" database.
Create the products table. This table will hold products record.
CREATE TABLE IF NOT EXISTS `products` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(512) NOT NULL, `description` text NOT NULL, `price` decimal(10,2) NOT NULL, `created` datetime NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='products that can be added to cart' AUTO_INCREMENT=41 ;
Create product_images table. This table will hold images related to product.
CREATE TABLE IF NOT EXISTS `product_images` ( `id` int(11) NOT NULL AUTO_INCREMENT, `product_id` int(11) NOT NULL, `name` varchar(512) NOT NULL, `created` datetime NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='image files related to a product' AUTO_INCREMENT=105 ;
Create cart_items table. This table will hold cart items of our user.
CREATE TABLE IF NOT EXISTS `cart_items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `product_id` int(11) NOT NULL, `quantity` double NOT NULL, `user_id` int(11) NOT NULL, `created` datetime NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=40 ;
The products and product_images table will not fully work without the sample data and images in the "/uploads/images/" directory.
You'll have to download the SQL and image files. Use the download button below. What will you get? A ZIP file with shop_cart_mysql_1.sql and 28 image files inside (1.30 MB).
Once downloaded, you may import the SQL file using PhpMyAdmin. Put the image files in "/uploads/images/" directory. You are now one step closer to the output shown in section 2.1 above.
4.3 Database connection file
Create "config" folder and inside it, create "database.php" file with the following code.
<?php // used to get mysql database connection class Database{ // specify your own database credentials private $host = "localhost"; private $db_name = "shop_cart_mysql_1"; private $username = "root"; private $password = ""; public $conn; // get the database connection public function getConnection(){ $this->conn = null; try{ $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password); }catch(PDOException $exception){ echo "Connection error: " . $exception->getMessage(); } return $this->conn; } } ?>
4.4 Output
Output screenshots are coming soon!
5.0 Prepare the user interface
Layout files are needed so we can use the same header and footer code.
5.1 Create header layout file
Create layout_head.php file and place the the following code.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><?php echo isset($page_title) ? $page_title : "The Code of a Ninja"; ?></title> <!-- Latest compiled and minified Bootstrap CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" /> <!-- custom css for users --> <link href="libs/css/user.css" rel="stylesheet" media="screen"> </head> <body> <?php include 'navigation.php'; ?> <!-- container --> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="page-header"> <h1><?php echo isset($page_title) ? $page_title : "The Code of a Ninja"; ?></h1> </div> </div>
5.2 Create footer layout file
Create layout_foot.php file and place the following code.
</div> <!-- /row --> </div> <!-- /container --> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <!-- Latest compiled and minified Bootstrap JavaScript --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <!-- custom script will be here --> </body> </html>
5.3 Create navigation.php
The "layout_head.php" will not work without the navigation.php file. Create that file and put the following code inside.
<!-- navbar --> <div class="navbar navbar-default navbar-static-top" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="products.php">XYZ Webstore</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <!-- highlight if $page_title has 'Products' word. --> <li <?php echo strpos($page_title, "Product")!==false ? "class='active'" : ""; ?>> <a href="products.php">Products</a> </li> <li <?php echo $page_title=="Cart" ? "class='active'" : ""; ?> > <a href="cart.php"> <!--later, we'll put a PHP code here that will count items in the cart --> Cart <span class="badge" id="comparison-count">0</span> </a> </li> </ul> </div><!--/.nav-collapse --> </div> </div> <!-- /navbar -->
5.4 Add Custom CSS
Inside "libs/css" directory, create user.css with the following code inside it.
.text-align-center{ text-align:center; } .f-w-b{ font-weight:bold; } .display-none{ display:none; } .w-5-pct{ width:5%; } .w-10-pct{ width:10%; } .w-15-pct{ width:15%; } .w-20-pct{ width:20%; } .w-25-pct{ width:25%; } .w-30-pct{ width:30%; } .w-35-pct{ width:35%; } .w-40-pct{ width:40%; } .w-45-pct{ width:45%; } .w-50-pct{ width:50%; } .w-55-pct{ width:55%; } .w-60-pct{ width:60%; } .w-65-pct{ width:65%; } .w-70-pct{ width:70%; } .w-75-pct{ width:75%; } .w-80-pct{ width:80%; } .w-85-pct{ width:85%; } .w-90-pct{ width:90%; } .w-95-pct{ width:95%; } .w-100-pct{ width:100%; } .m-t-0px{ margin-top:0px; } .m-b-10px{ margin-bottom:10px; } .m-b-20px{ margin-bottom:20px; } .m-b-30px{ margin-bottom:30px; } .m-b-40px{ margin-bottom:40px; } .stock-text { font-weight: bold; color: #008a00; } .stock-text-red{ font-weight:bold; color:#b12704; } .product-detail { font-weight: bold; margin: 0 0 5px 0; } .blueimp-gallery>.prev, .blueimp-gallery>.next{ border:none; } .update-quantity-form { width: 150px; float: left; margin: 0 10px 0 0; } .cart-row { border-bottom: thin solid #f1f1f1; overflow: hidden; width: 100%; padding: 20px 0 20px 0; } .product-link{ color:#000000; } .product-link:hover{ color:#000000; text-decoration:none; } .product-img-thumb { margin: 0 0 10px 0; width: 100%; cursor: pointer; }
6.0 Display Products
6.1 Create products.php
Now we are going to start displaying products from the database. Create products.php with the following basic code.
<?php // set page title $page_title="Products"; // page header html include 'layout_head.php'; // contents will be here // layout footer code include 'layout_foot.php'; ?>
6.2 Include PHP Classes
Put the following code after the opening "php" tag of the previous section.
// connect to database include 'config/database.php'; // include objects include_once "objects/product.php"; include_once "objects/product_image.php"; include_once "objects/cart_item.php"; // connect to database here
6.3 Create "product" object file
Create "objects" folder. Inside it, create product.php file with the following code.
<?php // 'product' object class Product{ // database connection and table name private $conn; private $table_name="products"; // object properties public $id; public $name; public $price; public $description; public $category_id; public $category_name; public $timestamp; // constructor public function __construct($db){ $this->conn = $db; } }
6.4 Create "product image" object file
Create product_image.php file inside "objects" folder.
<?php // 'product image' object class ProductImage{ // database connection and table name private $conn; private $table_name = "product_images"; // object properties public $id; public $product_id; public $name; public $timestamp; // constructor public function __construct($db){ $this->conn = $db; } }
6.5 Create "cart item" object file
Create cart_item.php file inside "objects" folder.
<?php // 'cart item' object class CartItem{ // database connection and table name private $conn; private $table_name = "cart_items"; // object properties public $id; public $product_id; public $quantity; public $user_id; public $created; public $modified; // constructor public function __construct($db){ $this->conn = $db; } }
6.6 Connect to the database
Replace "// connect to database here" comment in products.php file with the following code.
// get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $product = new Product($db); $product_image = new ProductImage($db); $cart_item = new CartItem($db);
6.7 Initialize action and pagination
Put the following code after the code on the previous section.
// to prevent undefined index notice $action = isset($_GET['action']) ? $_GET['action'] : ""; // for pagination purposes $page = isset($_GET['page']) ? $_GET['page'] : 1; // page is the current page, if there's nothing set, default is page 1 $records_per_page = 6; // set records or rows of data per page $from_record_num = ($records_per_page * $page) - $records_per_page; // calculate for the query LIMIT clause
6.8 Request data from the database
Request data from the database. Put the following code after the code on the previous section.
// read all products in the database $stmt=$product->read($from_record_num, $records_per_page); // count number of retrieved products $num = $stmt->rowCount(); // if products retrieved were more than zero if($num>0){ // needed for paging $page_url="products.php?"; $total_rows=$product->count(); // show products include_once "read_products_template.php"; } // tell the user if there's no products in the database else{ echo "<div class='col-md-12'>"; echo "<div class='alert alert-danger'>No products found.</div>"; echo "</div>"; }
6.9 Add "read" and "count" methods
The previous section will not work without the following code inside "objects/product.php" object file.
// read all products function read($from_record_num, $records_per_page){ // select all products query $query = "SELECT id, name, description, price FROM " . $this->table_name . " ORDER BY created DESC LIMIT ?, ?"; // prepare query statement $stmt = $this->conn->prepare( $query ); // bind limit clause variables $stmt->bindParam(1, $from_record_num, PDO::PARAM_INT); $stmt->bindParam(2, $records_per_page, PDO::PARAM_INT); // execute query $stmt->execute(); // return values return $stmt; } // used for paging products public function count(){ // query to count all product records $query = "SELECT count(*) FROM " . $this->table_name; // prepare query statement $stmt = $this->conn->prepare( $query ); // execute query $stmt->execute(); // get row value $rows = $stmt->fetch(PDO::FETCH_NUM); // return count return $rows[0]; }
6.10 Template to display products
The previous section won't work without "read_products_template.php", so create that file and put the following code.
<?php while($row = $stmt->fetch(PDO::FETCH_ASSOC)){ extract($row); // creating box echo "<div class='col-md-4 m-b-20px'>"; // product id for javascript access echo "<div class='product-id display-none'>{$id}</div>"; echo "<a href='product.php?id={$id}' class='product-link'>"; // select and show first product image $product_image->product_id=$id; $stmt_product_image=$product_image->readFirst(); while ($row_product_image = $stmt_product_image->fetch(PDO::FETCH_ASSOC)){ echo "<div class='m-b-10px'>"; echo "<img src='uploads/images/{$row_product_image['name']}' class='w-100-pct' />"; echo "</div>"; } // product name echo "<div class='product-name m-b-10px'>{$name}</div>"; echo "</a>"; // product price and category name echo "<div class='m-b-10px'>"; echo "$" . number_format($price, 2, '.', ','); echo "</div>"; // add to cart button echo "<div class='m-b-10px'>"; // cart item settings $cart_item->user_id=1; // we default to a user with ID "1" for now $cart_item->product_id=$id; // if product was already added in the cart if($cart_item->exists()){ echo "<a href='cart.php' class='btn btn-success w-100-pct'>"; echo "Update Cart"; echo "</a>"; }else{ echo "<a href='add_to_cart.php?id={$id}&page={$page}' class='btn btn-primary w-100-pct'>Add to Cart</a>"; } echo "</div>"; echo "</div>"; } include_once "paging.php"; ?>
6.11 Add "readFirst()" method
Add "readFirst()" method in "objects/product_image.php" file. The previous section will not work without it.
// read the first product image related to a product function readFirst(){ // select query $query = "SELECT id, product_id, name FROM " . $this->table_name . " WHERE product_id = ? ORDER BY name DESC LIMIT 0, 1"; // prepare query statement $stmt = $this->conn->prepare( $query ); // sanitize $this->id=htmlspecialchars(strip_tags($this->id)); // bind prodcut id variable $stmt->bindParam(1, $this->product_id); // execute query $stmt->execute(); // return values return $stmt; }
6.12 Add "exists()" method
Open /objects/cart_item.php and add the following method. This method checks if an item is already added to cart or not.
// check if a cart item exists public function exists(){ // query to count existing cart item $query = "SELECT count(*) FROM " . $this->table_name . " WHERE product_id=:product_id AND user_id=:user_id"; // prepare query statement $stmt = $this->conn->prepare( $query ); // sanitize $this->product_id=htmlspecialchars(strip_tags($this->product_id)); $this->user_id=htmlspecialchars(strip_tags($this->user_id)); // bind category id variable $stmt->bindParam(":product_id", $this->product_id); $stmt->bindParam(":user_id", $this->user_id); // execute query $stmt->execute(); // get row value $rows = $stmt->fetch(PDO::FETCH_NUM); // return if($rows[0]>0){ return true; } return false; }
6.13 Create pagination file
The previous section won't work without the paging.php file. Create paging.php with the following code.
<?php echo "<div class='col-md-12'>"; echo "<ul class='pagination m-b-20px m-t-0px'>"; // button for first page if($page>1){ echo "<li><a href='{$page_url}' title='Go to the first page.'>"; echo "First Page"; echo "</a></li>"; } $total_pages = ceil($total_rows / $records_per_page); // range of links to show $range = 2; // display links to 'range of pages' around 'current page' $initial_num = $page - $range; $condition_limit_num = ($page + $range) + 1; for ($x=$initial_num; $x<$condition_limit_num; $x++) { // be sure '$x is greater than 0' AND 'less than or equal to the $total_pages' if (($x > 0) && ($x <= $total_pages)) { // current page if ($x == $page) { echo "<li class='active'><a href=\"#\">$x <span class=\"sr-only\">(current)</span></a></li>"; } // not current page else { echo "<li><a href='{$page_url}page=$x'>$x</a></li>"; } } } // button for last page if($page<$total_pages){ echo "<li>"; echo "<a href='" . $page_url . "page={$total_pages}' title='Last page is {$total_pages}.'>"; echo "Last Page"; echo "</a>"; echo "</li>"; } echo "</ul>"; echo "</div>"; ?>
6.14 Output
Output screenshots are coming soon!
7.0 How to count items in the cart?
7.1 Display count in navigation bar
Open navigation.php and change this line:
<!--later, we'll put a PHP code here that will count items in the cart --> Cart <span class="badge" id="comparison-count">0</span>
to this:
<a href="cart.php"> <?php // count products in cart $cart_item->user_id=1; // default to user with ID "1" for now $cart_count=$cart_item->count(); ?> Cart <span class="badge" id="comparison-count"><?php echo $cart_count; ?></span> </a>
7.2 Cart item count() method
Open /objects/cart_item.php and put the count() method.
// count user's items in the cart public function count(){ // query to count existing cart item $query = "SELECT count(*) FROM " . $this->table_name . " WHERE user_id=:user_id"; // prepare query statement $stmt = $this->conn->prepare( $query ); // sanitize $this->user_id=htmlspecialchars(strip_tags($this->user_id)); // bind category id variable $stmt->bindParam(":user_id", $this->user_id); // execute query $stmt->execute(); // get row value $rows = $stmt->fetch(PDO::FETCH_NUM); // return return $rows[0]; }
7.3 Output
Output screenshots are coming soon!
8.0 How to add to cart?
8.1 Make "add to cart" button work
Put the following code before ending "body" tag of layout_foot.php file.
<script> $(document).ready(function(){ // add to cart button listener $('.add-to-cart-form').on('submit', function(){ // info is in the table / single product layout var id = $(this).find('.product-id').text(); var quantity = $(this).find('.cart-quantity').val(); // redirect to add_to_cart.php, with parameter values to process the request window.location.href = "add_to_cart.php?id=" + id + "&quantity=" + quantity; return false; }); }); </script>
8.2 Create add_to_cart.php
Create add_to_cart.php file because when 'Add to cart' button was clicked, that file with the following code inside will be executed.
<?php // parameters $product_id = isset($_GET['id']) ? $_GET['id'] : ""; $quantity = isset($_GET['quantity']) ? $_GET['quantity'] : 1; // make quantity a minimum of 1 $quantity=$quantity<=0 ? 1 : $quantity; // connect to database include 'config/database.php'; // include object include_once "objects/cart_item.php"; // get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $cart_item = new CartItem($db); // set cart item values $cart_item->user_id=1; // we default to '1' because we do not have logged in user $cart_item->product_id=$product_id; $cart_item->quantity=$quantity; // check if the item is in the cart, if it is, do not add if($cart_item->exists()){ // redirect to product list and tell the user it was added to cart header("Location: cart.php?action=exists"); } // else, add the item to cart else{ // add to cart if($cart_item->create()){ // redirect to product list and tell the user it was added to cart header("Location: product.php?id={$product_id}&action=added"); }else{ header("Location: product.php?id={$product_id}&action=unable_to_add"); } } ?>
8.3 Put create() method
The previous section will not work without the following code inside our /objects/cart_item.php file.
// create cart item record function create(){ // to get times-tamp for 'created' field $this->created=date('Y-m-d H:i:s'); // query to insert cart item record $query = "INSERT INTO " . $this->table_name . " SET product_id = :product_id, quantity = :quantity, user_id = :user_id, created = :created"; // prepare query statement $stmt = $this->conn->prepare($query); // sanitize $this->product_id=htmlspecialchars(strip_tags($this->product_id)); $this->quantity=htmlspecialchars(strip_tags($this->quantity)); $this->user_id=htmlspecialchars(strip_tags($this->user_id)); // bind values $stmt->bindParam(":product_id", $this->product_id); $stmt->bindParam(":quantity", $this->quantity); $stmt->bindParam(":user_id", $this->user_id); $stmt->bindParam(":created", $this->created); // execute query if($stmt->execute()){ return true; } return false; }
8.4 Create cart.php
Create cart.php with the following basic code.
<?php // connect to database include 'config/database.php'; // include objects include_once "objects/product.php"; include_once "objects/product_image.php"; include_once "objects/cart_item.php"; // get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $product = new Product($db); $product_image = new ProductImage($db); $cart_item = new CartItem($db); // set page title $page_title="Cart"; // include page header html include 'layout_head.php'; // contents will be here // layout footer include 'layout_foot.php'; ?>
8.5 Display message based on action
We'll display message on cart.php based on given action. Put the following code after "include 'layout_head.php';" of the previous section.
$action = isset($_GET['action']) ? $_GET['action'] : ""; echo "<div class='col-md-12'>"; if($action=='removed'){ echo "<div class='alert alert-info'>"; echo "Product was removed from your cart!"; echo "</div>"; } else if($action=='quantity_updated'){ echo "<div class='alert alert-info'>"; echo "Product quantity was updated!"; echo "</div>"; } else if($action=='exists'){ echo "<div class='alert alert-info'>"; echo "Product already exists in your cart!"; echo "</div>"; } else if($action=='cart_emptied'){ echo "<div class='alert alert-info'>"; echo "Cart was emptied."; echo "</div>"; } else if($action=='updated'){ echo "<div class='alert alert-info'>"; echo "Quantity was updated."; echo "</div>"; } else if($action=='unable_to_update'){ echo "<div class='alert alert-danger'>"; echo "Unable to update quantity."; echo "</div>"; } echo "</div>";
8.6 Display cart items
Put the following code based on the code of the previous section.
// $cart_count variable is initialized in navigation.php if($cart_count>0){ $cart_item->user_id="1"; $stmt=$cart_item->read(); $total=0; $item_count=0; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){ extract($row); $sub_total=$price*$quantity; echo "<div class='cart-row'>"; echo "<div class='col-md-8'>"; // product name echo "<div class='product-name m-b-10px'>"; echo "<h4>{$name}</h4>"; echo "</div>"; // update quantity echo "<form class='update-quantity-form'>"; echo "<div class='product-id' style='display:none;'>{$id}</div>"; echo "<div class='input-group'>"; echo "<input type='number' name='quantity' value='{$quantity}' class='form-control cart-quantity' min='1' />"; echo "<span class='input-group-btn'>"; echo "<button class='btn btn-default update-quantity' type='submit'>Update</button>"; echo "</span>"; echo "</div>"; echo "</form>"; // delete from cart echo "<a href='remove_from_cart.php?id={$id}' class='btn btn-default'>"; echo "Delete"; echo "</a>"; echo "</div>"; echo "<div class='col-md-4'>"; echo "<h4>$" . number_format($price, 2, '.', ',') . "</h4>"; echo "</div>"; echo "</div>"; $item_count += $quantity; $total+=$sub_total; } echo "<div class='col-md-8'></div>"; echo "<div class='col-md-4'>"; echo "<div class='cart-row'>"; echo "<h4 class='m-b-10px'>Total ({$item_count} items)</h4>"; echo "<h4>$" . number_format($total, 2, '.', ',') . "</h4>"; echo "<a href='checkout.php' class='btn btn-success m-b-10px'>"; echo "<span class='glyphicon glyphicon-shopping-cart'></span> Proceed to Checkout"; echo "</a>"; echo "</div>"; echo "</div>"; } else{ echo "<div class='col-md-12'>"; echo "<div class='alert alert-danger'>"; echo "No products found in your cart!"; echo "</div>"; echo "</div>"; }
8.7 Put read() method in cart item object
Open /objects/cart_item.php and add the following code. The previous section will not work without it. This read() method will query the database and return the products added to the cart.
// read items in the cart public function read(){ $query="SELECT p.id, p.name, p.price, ci.quantity, ci.quantity * p.price AS subtotal FROM " . $this->table_name . " ci LEFT JOIN products p ON ci.product_id = p.id WHERE ci.user_id=:user_id"; // prepare query statement $stmt = $this->conn->prepare($query); // sanitize $this->user_id=htmlspecialchars(strip_tags($this->user_id)); // bind value $stmt->bindParam(":user_id", $this->user_id, PDO::PARAM_INT); // execute query $stmt->execute(); // return values return $stmt; }
8.8 Read products by IDs
The previous section will not work without the following "readByIds()" method inside "objects/product.php" file.
// read all product based on product ids included in the $ids variable // reference http://stackoverflow.com/a/10722827/827418 public function readByIds($ids){ $ids_arr = str_repeat('?,', count($ids) - 1) . '?'; // query to select products $query = "SELECT id, name, price FROM " . $this->table_name . " WHERE id IN ({$ids_arr}) ORDER BY name"; // prepare query statement $stmt = $this->conn->prepare($query); // execute query $stmt->execute($ids); // return values from database return $stmt; }
8.9 Output
Output screenshots are coming soon!
9.0 How to update cart?
9.1 Update cart quantity with JavaScript
We have the 'update' button on cart.php file. When that button was clicked, a javascript code is triggered. Put the following code inside "$(document).ready(function(){" of layout_foot.php file.
// update quantity button listener $('.update-quantity-form').on('submit', function(){ // get basic information for updating the cart var id = $(this).find('.product-id').text(); var quantity = $(this).find('.cart-quantity').val(); // redirect to update_quantity.php, with parameter values to process the request window.location.href = "update_quantity.php?id=" + id + "&quantity=" + quantity; return false; });
9.2 PHP script to update cart
The previous section will not work without the update_quantity.php file with the following code inside it.
<?php // get the product id $product_id = isset($_GET['id']) ? $_GET['id'] : 1; $quantity = isset($_GET['quantity']) ? $_GET['quantity'] : ""; // make quantity a minimum of 1 $quantity=$quantity<=0 ? 1 : $quantity; // connect to database include 'config/database.php'; // include object include_once "objects/cart_item.php"; // get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $cart_item = new CartItem($db); // set cart item values $cart_item->user_id=1; // we default to '1' because we do not have logged in user $cart_item->product_id=$product_id; $cart_item->quantity=$quantity; // add to cart if($cart_item->update()){ // redirect to product list and tell the user it was added to cart header("Location: cart.php?action=updated"); }else{ header("Location: cart.php?action=unable_to_update"); } ?>
9.3 Update cart item in database
The previous section will not work without the following update() method inside /objects/cart_item.php file.
// create cart item record function update(){ // query to insert cart item record $query = "UPDATE " . $this->table_name . " SET quantity=:quantity WHERE product_id=:product_id AND user_id=:user_id"; // prepare query statement $stmt = $this->conn->prepare($query); // sanitize $this->quantity=htmlspecialchars(strip_tags($this->quantity)); $this->product_id=htmlspecialchars(strip_tags($this->product_id)); $this->user_id=htmlspecialchars(strip_tags($this->user_id)); // bind values $stmt->bindParam(":quantity", $this->quantity); $stmt->bindParam(":product_id", $this->product_id); $stmt->bindParam(":user_id", $this->user_id); // execute query if($stmt->execute()){ return true; } return false; }
9.4 How to remove product from cart?
We have the 'remove' button on cart.php file. When that button was clicked, the remove_from_cart.php file with the following code will be executed.
<?php // get the product id $product_id = isset($_GET['id']) ? $_GET['id'] : ""; // connect to database include 'config/database.php'; // include object include_once "objects/cart_item.php"; // get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $cart_item = new CartItem($db); // remove cart item from database $cart_item->user_id=1; // we default to '1' because we do not have logged in user $cart_item->product_id=$product_id; $cart_item->delete(); // redirect to product list and tell the user it was added to cart header('Location: cart.php?action=removed&id=' . $id); ?>
9.5 Put delete() method
The previous section will not work without the following method inside our /objects/cart_item.php file.
// remove cart item by user and product public function delete(){ // delete query $query = "DELETE FROM " . $this->table_name . " WHERE product_id=:product_id AND user_id=:user_id"; $stmt = $this->conn->prepare($query); // sanitize $this->product_id=htmlspecialchars(strip_tags($this->product_id)); $this->user_id=htmlspecialchars(strip_tags($this->user_id)); // bind ids $stmt->bindParam(":product_id", $this->product_id); $stmt->bindParam(":user_id", $this->user_id); if($stmt->execute()){ return true; } return false; }
9.6 Create the checkout page
The checkout page looks like the cart page but the items cannot be updated or removed. It just like the summary of orders. Create checkout.php with the following code.
<?php // connect to database include 'config/database.php'; // include objects include_once "objects/product.php"; include_once "objects/product_image.php"; include_once "objects/cart_item.php"; // get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $product = new Product($db); $product_image = new ProductImage($db); $cart_item = new CartItem($db); // set page title $page_title="Checkout"; // include page header html include 'layout_head.php'; // $cart_count variable is initialized in navigation.php if($cart_count>0){ $cart_item->user_id="1"; $stmt=$cart_item->read(); $total=0; $item_count=0; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){ extract($row); $sub_total=$price*$quantity; echo "<div class='cart-row'>"; echo "<div class='col-md-8'>"; echo "<div class='product-name m-b-10px'><h4>{$name}</h4></div>"; echo $quantity>1 ? "<div>{$quantity} items</div>" : "<div>{$quantity} item</div>"; echo "</div>"; echo "<div class='col-md-4'>"; echo "<h4>$" . number_format($price, 2, '.', ',') . "</h4>"; echo "</div>"; echo "</div>"; $item_count += $quantity; $total+=$sub_total; } echo "<div class='col-md-12 text-align-center'>"; echo "<div class='cart-row'>"; if($item_count>1){ echo "<h4 class='m-b-10px'>Total ({$item_count} items)</h4>"; }else{ echo "<h4 class='m-b-10px'>Total ({$item_count} item)</h4>"; } echo "<h4>$" . number_format($total, 2, '.', ',') . "</h4>"; echo "<a href='place_order.php' class='btn btn-lg btn-success m-b-10px'>"; echo "<span class='glyphicon glyphicon-shopping-cart'></span> Place Order"; echo "</a>"; echo "</div>"; echo "</div>"; } else{ echo "<div class='col-md-12'>"; echo "<div class='alert alert-danger'>"; echo "No products found in your cart!"; echo "</div>"; echo "</div>"; } include 'layout_foot.php'; ?>
9.7 Create place_order.php
We'll use this file to show a "thank you" message and remove all items in the cart.
<?php // include classes include_once "config/database.php"; include_once "objects/cart_item.php"; // get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $cart_item = new CartItem($db); // remove all cart item by user, from database $cart_item->user_id=1; // we default to '1' because we do not have logged in user $cart_item->deleteByUser(); // set page title $page_title="Thank You!"; // include page header HTML include_once 'layout_head.php'; echo "<div class='col-md-12'>"; // tell the user order has been placed echo "<div class='alert alert-success'>"; echo "<strong>Your order has been placed!</strong> Thank you very much!"; echo "</div>"; echo "</div>"; // include page footer HTML include_once 'layout_foot.php';
9.8 Delete all items in the cart
The previous section will not work without the following method. Open /objects/cart_item.php and put it inside.
// remove cart items by user public function deleteByUser(){ // delete query $query = "DELETE FROM " . $this->table_name . " WHERE user_id=:user_id"; $stmt = $this->conn->prepare($query); // sanitize $this->user_id=htmlspecialchars(strip_tags($this->user_id)); // bind id $stmt->bindParam(":user_id", $this->user_id); if($stmt->execute()){ return true; } return false; }
9.9 Output
Output screenshots are coming soon!
10.0 How to make the product page?
10.1 Create product.php
Create product.php with the following basic code.
<?php // include classes include_once "config/database.php"; include_once "objects/product.php"; include_once "objects/product_image.php"; include_once "objects/cart_item.php"; // get database connection $database = new Database(); $db = $database->getConnection(); // initialize objects $product = new Product($db); $product_image = new ProductImage($db); $cart_item = new CartItem($db); // get ID of the product to be edited $id = isset($_GET['id']) ? $_GET['id'] : die('ERROR: missing ID.'); $action = isset($_GET['action']) ? $_GET['action'] : ""; // set the id as product id property $product->id = $id; // to read single record product $product->readOne(); // set page title $page_title = $product->name; // include page header HTML include_once 'layout_head.php'; // content will be here // include page footer HTML include_once 'layout_foot.php'; ?>
10.2 Read product details
Put the following code after "$product_image = new ProductImage($db);" code of the previous section.
// get ID of the product to be edited and action $id = isset($_GET['id']) ? $_GET['id'] : die('ERROR: missing ID.'); $action = isset($_GET['action']) ? $_GET['action'] : ""; // set the id as product id property $product->id = $id; // to read single record product $product->readOne(); // set page title $page_title = $product->name;
10.3 Read one product method
The previous section will not work without the "readOne()" method. Add the following method inside "objects/product.php" file.
// used when filling up the update product form function readOne(){ // query to select single record $query = "SELECT name, description, price FROM " . $this->table_name . " WHERE id = ? LIMIT 0,1"; // prepare query statement $stmt = $this->conn->prepare( $query ); // sanitize $this->id=htmlspecialchars(strip_tags($this->id)); // bind product id value $stmt->bindParam(1, $this->id); // execute query $stmt->execute(); // get row values $row = $stmt->fetch(PDO::FETCH_ASSOC); // assign retrieved row value to object properties $this->name = $row['name']; $this->description = $row['description']; $this->price = $row['price']; }
10.4 Display message based on action
Open product.php file. Put the following code after ,span class="coan_code">include_once 'layout_head.php'; code.
echo "<div class='col-md-12'>"; if($action=='added'){ echo "<div class='alert alert-info'>"; echo "Product was added to your cart!"; echo "</div>"; } else if($action=='unable_to_add'){ echo "<div class='alert alert-info'>"; echo "Unable to add product to cart. Please contact Admin."; echo "</div>"; } echo "</div>"; // product thumbnail will be here
10.5 Display product thumbnails
When these product thumbnails were hovered, it displayes a larger version of the image. It is Amazon-style.
Open product.php file and replace // product thumbnail will be here comment with the following code.
// set product id $product_image->product_id=$id; // read all related product image $stmt_product_image = $product_image->readByProductId(); // count all relatd product image $num_product_image = $stmt_product_image->rowCount(); echo "<div class='col-md-1'>"; // if count is more than zero if($num_product_image>0){ // loop through all product images while ($row = $stmt_product_image->fetch(PDO::FETCH_ASSOC)){ // image name and source url $product_image_name = $row['name']; $source="uploads/images/{$product_image_name}"; echo "<img src='{$source}' class='product-img-thumb' data-img-id='{$row['id']}' />"; } }else{ echo "No images."; } echo "</div>";
10.6 Read images related to product
The previous section section will not work without the "readByProductId()" method inside "objects/product_image.php" file.
// read all product image related to a product function readByProductId(){ // select query $query = "SELECT id, product_id, name FROM " . $this->table_name . " WHERE product_id = ? ORDER BY name ASC"; // prepare query statement $stmt = $this->conn->prepare( $query ); // sanitize $this->product_id=htmlspecialchars(strip_tags($this->product_id)); // bind prodcut id variable $stmt->bindParam(1, $this->product_id); // execute query $stmt->execute(); // return values return $stmt; }
10.7 Display product image
Only one product image are displayed at a time. This part displays the larger product image based on the hovered product thumbnail. Put the following code after the previous section's code.
echo "<div class='col-md-4' id='product-img'>"; // read all related product image $stmt_product_image = $product_image->readByProductId(); $num_product_image = $stmt_product_image->rowCount(); // if count is more than zero if($num_product_image>0){ // loop through all product images $x=0; while ($row = $stmt_product_image->fetch(PDO::FETCH_ASSOC)){ // image name and source url $product_image_name = $row['name']; $source="uploads/images/{$product_image_name}"; $show_product_img=$x==0 ? "display-block" : "display-none"; echo "<a href='{$source}' target='_blank' id='product-img-{$row['id']}' class='product-img {$show_product_img}'>"; echo "<img src='{$source}' style='width:100%;' />"; echo "</a>"; $x++; } }else{ echo "No images."; } echo "</div>";
10.8 Make image hover work
Put the following jQuery code inside "$(document).ready(function(){" of layout_foot.php file.
// change product image on hover $(document).on('mouseenter', '.product-img-thumb', function(){ var data_img_id = $(this).attr('data-img-id'); $('.product-img').hide(); $('#product-img-'+data_img_id).show(); });
10.9 Display product details
This part display product price, description and category. Put the following code after the previous section's code.
echo "<div class='col-md-5'>"; echo "<div class='product-detail'>Price:</div>"; echo "<h4 class='m-b-10px price-description'>$" . number_format($product->price, 2, '.', ',') . "</h4>"; echo "<div class='product-detail'>Product description:</div>"; echo "<div class='m-b-10px'>"; // make html $page_description = htmlspecialchars_decode(htmlspecialchars_decode($product->description)); // show to user echo $page_description; echo "</div>"; echo "<div class='product-detail'>Product category:</div>"; echo "<div class='m-b-10px'>{$product->category_name}</div>"; echo "</div>";
10.10 Render 'Cart' button
Now we will display 'Add to cart' button if the product is not yet added to cart. Else, we will display 'update cart' button.
Place the following code after the previous section's code.
echo "<div class='col-md-2'>"; // cart item settings $cart_item->user_id=1; // we default to a user with ID "1" for now $cart_item->product_id=$id; // if product was already added in the cart if($cart_item->exists()){ echo "<div class='m-b-10px'>This product is already in your cart.</div>"; echo "<a href='cart.php' class='btn btn-success w-100-pct'>"; echo "Update Cart"; echo "</a>"; } // if product was not added to the cart yet else{ echo "<form class='add-to-cart-form'>"; // product id echo "<div class='product-id display-none'>{$id}</div>"; // select quantity echo "<div class='m-b-10px f-w-b'>Quantity:</div>"; echo "<input type='number' class='form-control m-b-10px cart-quantity' value='1' min='1' />"; // enable add to cart button echo "<button style='width:100%;' type='submit' class='btn btn-primary add-to-cart m-b-10px'>"; echo "<span class='glyphicon glyphicon-shopping-cart'></span> Add to cart"; echo "</button>"; echo "</form>"; } echo "</div>";
10.11 Output
Output screenshots are coming soon!
11.0 What People Say About This Code?
I'm so glad that this code delights other people. The following are some of them from the comments section!
★★★★★ "Hey Mike, my name is Leonardo from Argentina. I've been reading your blog since like 4 months from now, and I really must say: your tutorials are very good, they has helped me in many of my works... Well, thank you very much man. I really admire your work." ~ Leonardo
★★★★★ "Man, your tut's are awesome. Im so glad ive found your blog. Big respect!" ~ Milos
★★★★★ "I bought your level-2 source code and it was so good, very big help for me. It was worth it. Thank you very much!" ~ Ashley Deanna Plata
★★★★★ "Hello, This is a great script and I have paid 6.99 for your work (it Worth it)." ~ Louis Blais
★★★★★ "Words can't express how grateful I am for the work and the articles you post, had some troubles with doing somethings but your articles as per usual hit the hammer right on the head. They are a great way for expanding upon later too!" ~ Jeremy Smith
12.0 Download the LEVEL 1 Source Code
You can get the source code by following the whole, well detailed and free tutorial above. But isn’t it more convenient if you can just download the complete source code we used, and play around it?
There’s a small fee in getting the complete source code, it is small compared to the:
✔ Value or skill upgrade it can bring you, or | YES |
✔ Income you can get from your website project or business. | YES |
✔ Precious time you save. | YES |
✔ Expert advice and support (if you have any questions related to the source code) | YES |
For a limited time, I will give you the source code for a low price. DOWNLOAD THE SOURCE CODE LEVEL you desire by clicking its the BUY button below.
The LEVEL 1 Source code has the following features:
FEATURE | LEVEL 1 |
Learn to code a simple cart function | Yes |
List all products from MySQL database | Yes |
Add to cart action button | Yes |
Remove from cart action button | Yes |
Show message about a product added to cart | Yes |
Show message about a product removed from cart | Yes |
Navigation bar highlights which page is selected | Yes |
Cart link shows count of products added in the cart | Yes |
Show message if no products found in database | Yes |
Show message if no product found in cart | Yes |
Bootstrap enabled UI | Yes |
Cart page that lists all products added to cart | Yes |
Auto-compute total cost of all products added to cart | Yes |
Specify and save cart quantity | Yes |
Update cart quantity | Yes |
PDO extension used | Yes |
Step by step tutorial | Yes |
Free code updates | Yes |
Free support for 6 months | Yes |
13.0 Download the LEVEL 2 Source Code
Download the LEVEL 2 Source code, it has more features such as:
FEATURE | LEVEL 2 |
List all products from MySQL database | YES |
Pagination on products list page | YES |
Navigation bar has drop down of product categories | YES |
Highlight selected category in drop down | YES |
Categories are retrieved from the database | YES |
Show products by category | YES |
List products under a category with pagination | YES |
Search product | YES |
Search results with pagination | YES |
Search box located on upper right corner of navigation bar | YES |
Search box requires search term before clicking the search button | YES |
Add to cart action button | YES |
Quantity text box beside the add to cart button | YES |
Quantity text box required to be a number | YES |
Quantity text box required to have a minimum value of 1, negative value not allowed | YES |
Remember the page number where the user clicked the "Add to cart" button | YES |
Single product view | YES |
Add to cart text box and button in single product view | YES |
Quantity text box has up and down arrow for changing value | YES |
Remove from cart action button | YES |
Show message about a product added to cart | YES |
Disable products already added in the cart | YES |
Show message about a product removed from cart | YES |
Navigation bar highlights which page is selected | YES |
Cart link shows count of products added in the cart | YES |
Show message if no products found in database | YES |
Show message if no product found in cart | YES |
Well formatted money value | YES |
Check out button with cart icon | YES |
Bootstrap enabled UI | YES |
Cart page that lists all products added to cart | YES |
Quantity text box beside update quantity button | YES |
One click empty cart button | YES |
Auto-compute total cost of all products added to cart | YES |
Used PDO bindParam() to prevent SQL injection in MySQL queries | YES |
Used PHP htmlspecialchars() to prevent XSS attacks | YES |
SQL file is in the "dev" folder | YES |
PDO extension used | YES |
Free code updates | YES |
Free support for 6 months | YES |
14.0 Download the PHP Shopping Cart Module
It has several features you will enjoy learning. Some examples: how to handle the users, shopping cart and ordering using the PHP & MySQL technology. Click here to learn more or download it now using the button below.
15.0 Download the "PHP Shopping Cart SYSTEM" Source Code
Many of you requested this source code. You needed a shopping cart system with user management (merchant and customer), product management, category management, order management, security and more features based on our source codes here in codeofaninja.com. Click here to learn more.
16.0 What's Next?
We made another version of this tutorial. We used PHP session variables to store cart data. This is a great tutorial about PHP sessions.
You can find the tutorial here: PHP and MySQL Shopping Cart Tutorial – Using SESSIONS To Store Cart Data
17.0 Related Tutorials
18.0 Notes
#1 Found An Issue?
If you found a problem with this code, please write a comment below. Please be descriptive about your issue. Please provide the error messages, screenshots (or screencast) and your test URL. Thanks!Before you write a comment, remember to read this guide and our code of conduct.
#2 Become a true Ninja!
We constantly improve CodeOfaNinja. We update our tutorials and source codes. Receive valuable web programming tutorials and updates to your email. Subscribe now!
#3 Thank You!
Thank you for studying our tutorial about simple PHP MySQL shopping cart tutorial!