Posts

PHP Shopping Cart Tutorial – Step By Step Guide!

simple-php-mysql-shopping-cart-tutorial

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.

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.

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.

LEVEL 1 Source Code Output

[espro-slider id=6652]

LEVEL 2 Source Code Output

[espro-slider id=6622]

PHP Shopping Cart Module Output

[espro-slider id=6839]

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!

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

Prepare the database

Database Design

Our database name is "shop_cart_mysql_1", and we will have three (3) tables.
simple-php-mysql-shopping-cart-tutorial database design

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.

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;
	}

}
?>

Output

Output screenshots are coming soon!

Prepare the user interface

Layout files are needed so we can use the same header and footer code.

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>

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 -->

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;
}

Display Products

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';
?>

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

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;
	}
}

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;
	}
}

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;
    }
}

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);

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

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>";
}

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];
}

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";
?>

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;
}

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;
}

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>";
?>

Output

Output screenshots are coming soon!

How to count items in the cart?

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>

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];
}

Output

Output screenshots are coming soon!

How to add to cart?

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>

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");
	}
}
?>

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;
}

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';
?>

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>";

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;
}

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;
}

Output

Output screenshots are coming soon!

How to update cart?

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;
});

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");
}
?>

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;
}

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);
?>

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;
}

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';
?>

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';

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;
}

Output

Output screenshots are coming soon!

How to make the product page?

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';
?>

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;

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'];
}

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

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>";

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;
}

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();
});

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>";

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>";

Output

Output screenshots are coming soon!

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

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, orYES
✔ 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
$20 - Download now

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
$40 - Download now

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.

$50 - Download now

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.

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

Related Tutorials

Please explore more tutorials on our start page. Click here.

Notes

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.

Subscribe to CodeOfaNinja

We constantly improve CodeOfaNinja. We update our tutorials and source codes. Receive valuable web programming tutorials and updates to your email. Subscribe now!

Enjoy high-quality web programming tutorials.
Subscribe to CodeOfaNinja now for FREE!

Thank You!

Thank you for studying our tutorial about simple PHP MySQL shopping cart tutorial!

PHP and MySQL Shopping Cart Tutorial – Using COOKIES To Store Cart Data

php-shopping-cart-tutorial-using-cookies-1
Previously, we have learned how to code a shopping cart using PHP SESSIONS. Today, we will learn a second way to do it. We will have a PHP shopping cart tutorial using COOKIES!

Sounds delicious, isn't it? But the cookie that we will use is not the cookie we eat. Let me explain.

In this tutorial, we'll use the HTTP cookie, also known as the web cookie or browser cookie.

It is usually a small piece of data stored in the user's browser while the user is using the site.

It is designed to be a reliable way for websites to remember useful information, such as shopping cart items, or to record any user activity on a website.

PHP SESSIONS code works and was used by many websites before but nowadays it is more advisable to use cookies for your shopping cart program.

By the way, we'll also use my favourite front-end framework Bootstrap so that our sample shopping cart script will have a good looking user interface.

If you're not familiar with Bootstrap yet, please have a look at our step by step Bootstrap guide.

Why Use Cookies?

There are several reasons why you should use cookies when creating our shopping cart script. Here are some of the reasons I found useful for us to know.

  1. WooCommerce, a popular eCommerce plugin for WordPress, was previously using PHP sessions for storing cart data. But few years ago, they changed it and are now using cookies. One of the reasons they cited was "To reduce support regarding hosts and session configurations." I think that's also a big example and reason why we have to use cookies for storing cart data. See their version 2.0.0 change log her
  2. As explained earlier, cookies are designed to be a reliable mechanism for websites to remember information with certain state like the shopping cart items.
  3. Shopping cart items will stay even if the user closes the browser or shut down and restart his computer. It means the user can be reminded what he was going to buy from your website.

Code Output

LEVEL 1 Source Code Output

[espro-slider id=6652]

LEVEL 2 Source Code Output

[espro-slider id=6622]

LEVEL 3 Source Code Output

[espro-slider id=6839]

The LEVEL 2 and LEVEL 3 source code 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!

Files Overview of PHP Shopping Cart Tutorial Using Cookies

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_cookies_1.sql
├─── readme.txt
├─ images/
├─ libs/
├─── css/
├────── bootstrap/
├─── js/
├────── jquery.js
├─ objects/
├─── 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
├─ thank_you.php
├─ update_quantity.php

Prepare the database

Database Design

Our database name will be called "shop_cart_cookies_1", and we will have two (2) tables.
php shopping cart tutorial database design

Create MySQL Tables

You may run the following SQL queries on our "shop_cart_cookies_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 ;

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_cookies_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.

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_cookies_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;
    }
 
}
?>

Prepare the user interface

Download jQuery and Bootstrap

Download jQuery library here. Create "libs" folder. Inside it, create "js" folder. Put jQuery library inside "js" folder.

Download Bootstrap framework here. Inside "libs" folder, create "css" folder. Put bootstrap library inside "css" folder.

5.2 Create layout files

Layout files are needed so we can use the same header and footer code.

Create "layout_head.php" with 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>
 
    <!-- Bootstrap CSS -->
    <link href="libs/css/bootstrap/dist/css/bootstrap.css" rel="stylesheet" media="screen">
 
    <!-- HTML5 Shiv and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
 
    <!-- 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>

Create "layout_foot.php" with the following code.

        </div>
        <!-- /row -->
 
    </div>
    <!-- /container -->
 
<!-- jQuery library -->
<script src="libs/js/jquery.js"></script>
 
<!-- bootstrap JavaScript -->
<script src="libs/css/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="libs/css/bootstrap/docs-assets/js/holder.js"></script>
 
</body>
</html>

Create navigation.php file and place the following code.

<!-- 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 dropdown'" : "class='dropdown'"; ?>>
                    <a href="products.php">Products</a>
                </li>
 
                <li <?php echo $page_title=="Cart" ? "class='active'" : ""; ?> >
                    <a href="cart.php">
                        <?php
                        // count items in the cart
                        $cookie = isset($_COOKIE['cart_items_cookie']) ? $_COOKIE['cart_items_cookie'] : "";
                        $cookie = stripslashes($cookie);
                        $saved_cart_items = json_decode($cookie, true);
                        $cart_count=count($saved_cart_items);
                        ?>
                        Cart <span class="badge" id="comparison-count"><?php echo $cart_count; ?></span>
                    </a>
                </li>
            </ul>
 
        </div><!--/.nav-collapse -->
 
    </div>
</div>
<!-- /navbar -->

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;
}

Display Products

Create products.php

Now we are going to start displaying products from the database. Create products.php with the following basic code.

<?php
// read items in the cart
$cookie = isset($_COOKIE['cart_items_cookie']) ? $_COOKIE['cart_items_cookie'] : "";
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// to prevent null value
$saved_cart_items=$saved_cart_items==null ? array() : $saved_cart_items;
 
// set page title
$page_title="Products";
 
// page header html
include 'layout_head.php';
 
// contents will be here 
 
// layout footer code
include 'layout_foot.php';
?>

Important Note: PHP cookies must be used before any HTML output. This will prevent failure of cookies to be read or write.

Include PHP Classes

Put the following code before the "$page_title" code of the previous section.

// connect to database
include 'config/database.php';

// include objects
include_once "objects/product.php";
include_once "objects/product_image.php";

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;
    }
}

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;
  

Connect to the database

Put the following code after the code on the previous section.

// get database connection
$database = new Database();
$db = $database->getConnection();
 
// initialize objects
$product = new Product($db);
$product_image = new ProductImage($db);

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

Display messages based on action

We'll display messages basedon given action. Put the following code after "include '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>";
    }
 
    if($action=='exists'){
        echo "<div class='alert alert-info'>";
            echo "Product already exists in your cart!";
        echo "</div>";
    }
echo "</div>";

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>";
}

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];
}

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>";
 
        // add to cart button
        echo "<div class='m-b-10px'>";
            if(array_key_exists($id, $saved_cart_items)){
                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 Make "add to cart" button work

<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>

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>";
?>

How to add to cart?

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
 
// get the product id
$id = isset($_GET['id']) ? $_GET['id'] : "";
$quantity = isset($_GET['quantity']) ? $_GET['quantity'] : 1;
$page = isset($_GET['page']) ? $_GET['page'] : 1;
 
// make quantity a minimum of 1
$quantity=$quantity<=0 ? 1 : $quantity;
 
// add new item on array
$cart_items[$id]=array(
    'quantity'=>$quantity
);
 
// read
$cookie = isset($_COOKIE['cart_items_cookie']) ? $_COOKIE['cart_items_cookie'] : "";
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// if $saved_cart_items is null, prevent null error
if(!$saved_cart_items){
    $saved_cart_items=array();
}
 
// check if the item is in the array, if it is, do not add
if(array_key_exists($id, $saved_cart_items)){
    // redirect to product list and tell the user it was added to cart
    header('Location: product.php?id=' . $id . '&action=exists');
}
 
// else, add the item to the array
else{
    // if cart has contents
    if(count($saved_cart_items)>0){
        foreach($saved_cart_items as $key=>$value){
            // add old item to array, it will prevent duplicate keys
            $cart_items[$key]=array(
                'quantity'=>$value['quantity']
            );
        }
    }
 
    // put item to cookie
    $json = json_encode($cart_items, true);
    setcookie("cart_items_cookie", $json, time() + (86400 * 30), '/'); // 86400 = 1 day
    $_COOKIE['cart_items_cookie']=$json;
 
    // redirect to product list and tell the user it was added to cart
    header('Location: product.php?id=' . $id . '&action=added');
}
die();
?>

Create cart.php

Create cart.php with the following basic code.

<?php
// read cookie contents
$cookie = isset($_COOKIE['cart_items_cookie']) ? $_COOKIE['cart_items_cookie'] : "";
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// connect to database
include 'config/database.php';
 
// include objects
include_once "objects/product.php";
include_once "objects/product_image.php";
 
// get database connection
$database = new Database();
$db = $database->getConnection();
 
// initialize objects
$product = new Product($db);
$product_image = new ProductImage($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';
?>

7.3 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=='empty_cart'){
        echo "<div class='alert alert-danger'>";
            echo "Cart was emptied!";
        echo "</div>";
    }
 
    else if($action=='exists'){
        echo "<div class='alert alert-info'>";
            echo "Product already exists in your cart!";
        echo "</div>";
    }
echo "</div>";

Display cart items

Put the following code based on the code of the previous section.

if(count($saved_cart_items)>0){
 
    echo "<div class='col-md-12'>";
        // remove all cart contents
        echo "<div class='right-button-margin' style='overflow:hidden;'>";
            echo "<button class='btn btn-default pull-right' id='empty-cart'>Empty Cart</button>";
        echo "</div>";
    echo "</div>";
 
    // get the product ids
    $ids = array();
    foreach($saved_cart_items as $id=>$name){
        array_push($ids, $id);
    }
 
    $stmt=$product->readByIds($ids);
 
    $total=0;
    $item_count=0;
 
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
        extract($row);
 
        $quantity=$saved_cart_items[$id]['quantity'];
        $sub_total=$price*$quantity;
 
        // =================
        echo "<div class='cart-row'>";
            echo "<div class='col-md-8'>";
 
                echo "<div class='product-name m-b-10px'>";
                    echo "<h4>{$name}</h4>";
                echo "</div>";
 
                // update quantity
                echo "<form class='update-quantity-form w-200-px'>";
                    echo "<div class='product-id' style='display:none;'>{$id}</div>";
                    echo "<input type='number' value='{$quantity}' name='quantity' class='form-control cart-quantity m-b-10px cart-quantity-dropdown' min='1' />";
                    echo "<button class='btn btn-default update-quantity' type='submit'>Update</button>";
                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>";
}

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;
}

How to update cart?

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;
});

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
$id = isset($_GET['id']) ? $_GET['id'] : 1;
$quantity = isset($_GET['quantity']) ? $_GET['quantity'] : "";
 
// make quantity a minimum of 1
$quantity=$quantity<=0 ? 1 : $quantity;
 
// read cookie
$cookie = $_COOKIE['cart_items_cookie'];
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// remove the item from the array
unset($saved_cart_items[$id]);
 
// delete cookie value
setcookie("cart_items_cookie", "", time()-3600);
 
// add the item with updated quantity
$saved_cart_items[$id]=array(
    'quantity'=>$quantity
);
 
// enter new value
$json = json_encode($saved_cart_items, true);
setcookie("cart_items_cookie", $json, time() + (86400 * 30), '/'); // 86400 = 1 day
$_COOKIE['cart_items_cookie']=$json;
 
// redirect to product list and tell the user it was added to cart
header('Location: cart.php?action=quantity_updated&id=' . $id);
die();
?>

How to remove product on 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
$id = isset($_GET['id']) ? $_GET['id'] : "";
 
// read
$cookie = $_COOKIE['cart_items_cookie'];
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// remove the item from the array
unset($saved_cart_items[$id]);
 
// delete cookie value
unset($_COOKIE["cart_items_cookie"]);
 
// empty value and expiration one hour before
setcookie("cart_items_cookie", "", time() - 3600);
 
// enter new value
$json = json_encode($saved_cart_items, true);
setcookie("cart_items_cookie", $json, time() + (86400 * 30), '/'); // 86400 = 1 day
$_COOKIE['cart_items_cookie']=$json;
 
// redirect to product list and tell the user it was added to cart
header('Location: cart.php?action=removed&id=' . $id);
die();
?>

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
// read cookie contents
$cookie = isset($_COOKIE['cart_items_cookie']) ? $_COOKIE['cart_items_cookie'] : "";
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// connect to database
include 'config/database.php';
 
// include objects
include_once "objects/product.php";
include_once "objects/product_image.php";
 
// get database connection
$database = new Database();
$db = $database->getConnection();
 
// initialize objects
$product = new Product($db);
$product_image = new ProductImage($db);
 
// set page title
$page_title="Checkout";
 
// include page header html
include 'layout_head.php';
 
if(count($saved_cart_items)>0){
 
    // get the product ids
    $ids = array();
    foreach($saved_cart_items as $id=>$name){
        array_push($ids, $id);
    }
 
    $stmt=$product->readByIds($ids);
 
    $total=0;
    $item_count=0;
 
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
        extract($row);
 
        $quantity=$saved_cart_items[$id]['quantity'];
        $sub_total=$price*$quantity;
 
        //echo "<div class='product-id' style='display:none;'>{$id}</div>";
        //echo "<div class='product-name'>{$name}</div>";
 
        // =================
        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-8'></div>";
    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';
?>

Create place_order.php

We'll use this file to show a "thank you" message and remove all items in the cart.

<?php
// you can do a lot more processing here but for now,
// we'll just empty the cart contents and redirect to a 'thank you' page
header('Location: empty_cart.php?redirect_to=thank_you');
die();
?>

Create empty_cart.php

This file will remove the contents of our cart once the order has been placed. Create empty_cart.php file. Place the following code.

<?php
header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');
 
// read
$cookie = $_COOKIE['cart_items_cookie'];
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// remove values
unset($saved_cart_items);
 
// delete cookie value
unset($_COOKIE["cart_items_cookie"]);
 
// empty value and expiration one hour before
setcookie("cart_items_cookie", "", time() - 3600);
 
// enter empty value
$json = json_encode($saved_cart_items, true);
setcookie("cart_items_cookie", $json, time() + (86400 * 30), '/'); // 86400 = 1 day
$_COOKIE['cart_items_cookie']=$json;
 
// redirect
$redirect_to=isset($_GET['redirect_to']) ? $_GET['redirect_to'] : "";
 
// redirect to thank you page
if($redirect_to=="thank_you"){
    header('Location: thank_you.php');
}
 
// redirect to cart
else{
    header('Location: cart.php?action=empty_cart');
}
die();
?>

Create Thank You Page

Once cart was emptied with parameter "redirect_to=thank_you" (like the one on the previous section), it will be redirected to this page.

<?php
// set page title
$page_title="Thank You!";
 
// include page header html
include 'layout_head.php';
 
echo "<div class='col-md-12'>";
    echo "<div class='alert alert-success'>";
        echo "Order has been placed, thank you!";
    echo "</div>";
echo "</div>";
 
include 'layout_foot.php';
?>

How to make the product page?

Create product.php

Create product.php with the following basic code.

<?php
// read items in the cart
$cookie = isset($_COOKIE['cart_items_cookie']) ? $_COOKIE['cart_items_cookie'] : "";
$cookie = stripslashes($cookie);
$saved_cart_items = json_decode($cookie, true);
 
// include classes
include_once "config/database.php";
include_once "objects/product.php";
include_once "objects/product_image.php";
 
// get database connection
$database = new Database();
$db = $database->getConnection();
 
// initialize objects
$product = new Product($db);
$product_image = new ProductImage($db);
 
// include page header HTML
include_once 'layout_head.php';
 
// content will be here
 
// include page footer HTML
include_once 'layout_foot.php';
?>

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
$id = isset($_GET['id']) ? $_GET['id'] : die('ERROR: missing ID.');
 
// set the id as product id property
$product->id = $id;
 
// to read single record product
$product->readOne();
 
// set page title
$page_title = $product->name;

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'];
}

9.4 Display product thumbnails

When these product thumbnails were hovered, it displayes a larger version of the image. It is Amazon-style. Put the following code after the previous section's 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>";

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;
}

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>";

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();
});

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>";

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.

echo "<div class='col-md-2'>";
 
    // to prevent null value
    $saved_cart_items=$saved_cart_items==null ? array() : $saved_cart_items;
 
    // if product was already added in the cart
    if(array_key_exists($id, $saved_cart_items)){
        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>";
 
            echo "<div class='m-b-10px f-w-b'>Quantity:</div>";
            echo "<input type='number' value='1' class='form-control m-b-10px cart-quantity' 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>";

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

Download the LEVEL 1 Source Code

You can get the source code by following the whole, well detailed 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, orYES
✔ Income you can get from your website project or business.YES
✔ Precious time you save.YES
✔ Expert advice you can get from us, just in case 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.

FEATURE LEVEL 1
Learn to code a simple cart function Yes
List all products from MySQL database Yes
Pagination on products list page YES
Add to cart action button Yes
Remove from cart action button Yes
Update cart quantity Yes
Checkout Page Yes
Place order / Thank you page Yes
Amazon-style product details page Yes
Change image on hover of thumbnail 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
PDO extension used Yes
Step by step tutorial Yes
Free code updates Yes
Free support for 6 months Yes
Download Now

Download the LEVEL 2 Source Code

FEATURE LEVEL 2
All features of LEVEL 1 source code 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
Quantity drop down options based on available stock YES
Well formatted money value YES
Check out button with cart icon YES
Product image viwable in lightbox YES
Shows number of stock left YES
Stock decreases once checked out YES
Order saved in orders and order_items table in the database YES
Emtpy cart button YES
Emtpy cart confirmation pop up YES
Bootstrap enabled UI YES
Cart page that lists all products added to cart YES
Quantity text box beside update quantity button YES
Show price, category and stocks left in product list page 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
Download Now

Download the LEVEL 3 Source Code

The LEVEL 3 source code is also known as our "PHP Shopping Cart & Ordering Module". It has several features you need to learn more about how to handle the users, shopping cart, and ordering using the PHP & MySQL technology. Click here to learn more

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.

What's Next?

We just learned how to code an online shopping cart from scratch using PHP and COOKIES.

But did you know that we can create the almost the same functions using plain PHP and MySQL?

If you're excited to learn this new concept, let us go to the next tutorial: How To Build A Simple Shopping Cart Website With PHP And MySQL?

Related Tutorials

Please explore more tutorials on our start page. Click here.

Some Notes

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.

Subscribe to CodeOfaNinja

We constantly improve CodeOfaNinja. We update our tutorials and source codes. Receive valuable web programming tutorials and updates to your email. Subscribe now!

Enjoy high-quality web programming tutorials.
Subscribe to CodeOfaNinja now for FREE!

Thank You!

Thanks for reading this PHP shopping cart tutorial using cookies!

PHP and MySQL Shopping Cart Tutorial – Using SESSIONS To Store Cart Data

shopping-cart-in-php-sessions

Previously, we learned how to build a Shopping Cart with PHP & MySQL where we used a database to store cart items. Today, we will learn another version of it. We will use PHP session variables to store cart items.

Overview

Introduction

If you want to build your own online shopping cart from scratch, we have good news for you!

This post can help you get it done because we will build a simple shopping cart script today.

We will use PHP, MySQL and PHP sessions to complete this task.

A lot of people use a ready-made software for this.

But for coders like us, it is important to learn and experience how to do it. We can create more features like making the system more secured, add some unique functionality and more.

Your imagination can be the only limit.

Is this code for you?

The source codes in this page is NOT for you if:

  • You are 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.

How to use this tutorial?

This tutorial is already working. You can proceed to the instructions below.

It is coming soon! Please subscribe here so you will be updated.

Tutorial 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.

LEVEL 1 Source Code Output

[espro-slider id=6652]

LEVEL 2 Source Code Output

[espro-slider id=6622]

The LEVEL 2 source code output proves that you can add and customize more features. It will be easier and faster if you will learn by following our tutorial below.

Downloading our source codes is your huge advantage as well.

If you need more features like product variations, admin features and user login, see our PHP Shopping Cart Module and PHP Shopping Cart System.

For now, let's proceed to the step by step tutorial of our LEVEL 1 source code. Enjoy!

File Structure

The following folders and files are included in the final source code of this tutorial. It will have more meaning if you will see the code inside the folders and files as we go through this tutorial.

The branch with backslash represents a folder. Everything else represents a file. It can be a PHP file, SQL file, text file, CSS file or JavaScript file.

├─ config/
├─── database.php
├─ dev/
├─── shop_cart_sessions_1.sql
├─── readme.txt
├─ images/
├─ libs/
├─── css/
├────── bootstrap/
├─── js/
├────── jquery.js
├─ objects/
├─── product_image.php
├─── product.php
├─ uploads/
├─── images/
├─ .htaccess
├─ add_to_cart.php
├─ cart.php
├─ checkout.php
├─ layout_footer.php
├─ layout_header.php
├─ navigation.php
├─ paging.php
├─ place_order.php
├─ product.php
├─ products.php
├─ read_products_template.php
├─ remove_from_cart.php
├─ update_quantity.php

Prepare the database

Database Design

Our database name will be called "shop_cart_sessions_1", and we will have two (2) tables. The image below is a visual representation of our database tables and how they are related.
php shopping cart tutorial database design

Create a database

Make sure your Apache and MySQL servers are running.

  • Open your PhpMyAdmin (http://localhost/phpmyadmin)
  • Create a new database.
  • Put "shop_cart_sessions_1" as database name.
  • Click "Create" button.

4.3 Create "products" table

In this section, we will create the "products" table (using PhpMyAdmin) on the database we just created. This table will hold the product records.

Here's how to run an SQL statement using PhpMyAdmin.

  • Click "shop_cart_sessions_1" database.
  • Click "SQL" tab.
  • Copy the SQL statement below and paste it in the text area.
  • Click the "Go" button.
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 "categories" table

This table will hold images related to product.

Run the following SQL statement using your PhpMyAdmin.

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 ;

Download sample data and images

The products and product_images table will not fully work without the sample data and related image files.

To make things easier, I decided to create a ZIP file with shop_cart_sessions_1.sql and 28 image files inside (1.30 MB).

Use the following button to download the ZIP file.

Extract and import data

Once downloaded, please extract the files.

Import the SQL file using PhpMyAdmin.

Put the image files in "php-shopping-cart-using-sessions-level-1/uploads/images/" directory. That directory does not exist yet. We need to create it now.

  • Create "php-shopping-cart-using-sessions-level-1" folder and open it. This is our project's main folder.
  • Create "uploads" folder and open it.
  • Create "images" folder and open it.
  • Copy and paste the images on this directory.

Database connection file

This file will be used to get connection to the database.

  • Open "php-shopping-cart-using-sessions-level-1" folder.
  • Create "config" folder and open it.
  • Create "database.php" file and open it.
  • Place 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_sessions_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;
	}

}
?>

Output

Our PhpMyAdmin should look like the image below. A database with two tables.

We don't have an actual program output yet because we only set up the database. Let's continue our tutorial below to achieve more outputs.

Create the layout files

Create header layout file

This “layout_header.php” file will be included at the beginning of the PHP files that will need it. This way, we won’t have to write the same header codes every time.

We use the Bootstrap framework to make our project look good. If you’re not yet familiar with you, please learn our Bootstrap tutorial here.

Bootstrap CSS asset will be included inside the head tags.

  • Open "php-shopping-cart-using-sessions-level-1" folder.
  • Create "layout_header.php" file.
  • Place the following code.
<?php
$_SESSION['cart']=isset($_SESSION['cart']) ? $_SESSION['cart'] : array();
?>
<!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" />

    <!-- our custom CSS -->
    <link rel="stylesheet" href="libs/css/custom.css" />

</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>

Create footer layout file

This "layout_footer.php" will be included at the end of the PHP files that will needs it. This way, we won’t have to write the same footer codes every time.

The assets used in this file are:

Let’s go on and create the footer layout file.

  • Open "php-shopping-cart-using-sessions-level-1" folder.
  • Create "layout_footer.php" file.
  • 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>

Create navigation layout file

This file will render the "Products" and "Cart" links that the user can click.

  • Open "php-shopping-cart-using-sessions-level-1" folder.
  • Create "navigation.php" file.
  • Place the following code.
<!-- 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 $page_title=="Products" ? "class='active'" : ""; ?>>
					<a href="products.php" class="dropdown-toggle">Products</a>
				</li>

				<li <?php echo $page_title=="Cart" ? "class='active'" : ""; ?> >
					<a href="cart.php">
						<?php
						// count products in cart
						$cart_count=count($_SESSION['cart']);
						?>
						Cart <span class="badge" id="comparison-count"><?php echo $cart_count; ?></span>
					</a>
				</li>
			</ul>

		</div><!--/.nav-collapse -->

	</div>
</div>
<!-- /navbar -->

Create custom CSS file

This custom.css file is where our custom styles are located.

  • Open "php-shopping-cart-using-sessions-level-1" folder.
  • Open "libs" folder.
  • Open "css" folder.
  • Create "custom.css" file.
  • Place the following code.
.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;
}

Output

The files we created in this section is meant to be used within another PHP file. If we will try to run the files, we won't see anything meaningful yet.

If you will run layout_header.php file, it will look like this.

The custom.css looks like this.

The navigation.php looks like this.

The footer.php is blank. Let's continue on the next section to see something meaningful.

Display Products

Create products.php

Now we are going to start displaying products from the database. Create products.php with the following basic code.

<?php
// start session
session_start();

// set page title
$page_title="Products";

// page header html
include 'layout_header.php';

// contents will be here 

// layout footer code
include 'layout_footer.php';
?>

Include PHP Classes

Put the following code after "session_start();" code of the previous section.

// connect to database
include 'config/database.php';

// include objects
include_once "objects/product.php";
include_once "objects/product_image.php";

// class instances will be here

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;
	}
}

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;
	}
}

Connect to the database

Open products.php file. Replace // class instances will be here comment with the following code.

// get database connection
$database = new Database();
$db = $database->getConnection();

// initialize objects
$product = new Product($db);
$product_image = new ProductImage($db);

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

Display messages based on action

We'll display messages basedon given action.

Put the following code after include 'layout_header.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>";
	}

	if($action=='exists'){
		echo "<div class='alert alert-info'>";
			echo "Product already exists in your cart!";
		echo "</div>";
	}
echo "</div>";

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>";
}

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];
}

Template to display products

The products.php won't work without "read_products_template.php", so create that file and put the following code.

<?php
if(!isset($_SESSION['cart'])){
	$_SESSION['cart']=array();
}

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>";

		// add to cart button
		echo "<div class='m-b-10px'>";
			if(array_key_exists($id, $_SESSION['cart'])){
				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";
?>

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;
}

Make "add to cart" button work

Open layout_footer.php file. Replace <!-- custom script will be here --> comment with the following code.

<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>

Create pagination file

The read_products_template.php file 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>";
?>

Output

Run your products.php file on the browser http://localhost/php-shopping-cart-using-sessions-level-1/products.php. You should see an output like the image below.

How to add to cart?

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
// start session
session_start();

// get the product id
$id = isset($_GET['id']) ? $_GET['id'] : "";
$quantity = isset($_GET['quantity']) ? $_GET['quantity'] : 1;
$page = isset($_GET['page']) ? $_GET['page'] : 1;

// make quantity a minimum of 1
$quantity=$quantity<=0 ? 1 : $quantity;

// add new item on array
$cart_item=array(
	'quantity'=>$quantity
);

/*
 * check if the 'cart' session array was created
 * if it is NOT, create the 'cart' session array
 */
if(!isset($_SESSION['cart'])){
	$_SESSION['cart'] = array();
}

// check if the item is in the array, if it is, do not add
if(array_key_exists($id, $_SESSION['cart'])){
	// redirect to product list and tell the user it was added to cart
	header('Location: products.php?action=exists&id=' . $id . '&page=' . $page);
}

// else, add the item to the array
else{
	$_SESSION['cart'][$id]=$cart_item;

	// redirect to product list and tell the user it was added to cart
	header('Location: products.php?action=added&page=' . $page);
}
?>

Create cart.php

Create cart.php with the following basic code.

<?php
// start session
session_start();

// connect to database
include 'config/database.php';

// include objects
include_once "objects/product.php";
include_once "objects/product_image.php";

// get database connection
$database = new Database();
$db = $database->getConnection();

// initialize objects
$product = new Product($db);
$product_image = new ProductImage($db);

// set page title
$page_title="Cart";

// include page header html
include 'layout_header.php';

// contents will be here 

// layout footer
include 'layout_footer.php';
?>

Display message based on action

We'll display message on cart.php based on given action.

Put the following code after include 'layout_header.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>";
	}
echo "</div>";

Display cart items

Put the following code after the code of the previous section.

if(count($_SESSION['cart'])>0){

	// get the product ids
	$ids = array();
	foreach($_SESSION['cart'] as $id=>$value){
		array_push($ids, $id);
	}

	$stmt=$product->readByIds($ids);

	$total=0;
	$item_count=0;

	while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
        extract($row);

		$quantity=$_SESSION['cart'][$id]['quantity'];
		$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>";

				// 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>";

}

// no products were added to cart
else{
	echo "<div class='col-md-12'>";
		echo "<div class='alert alert-danger'>";
			echo "No products found in your cart!";
		echo "</div>";
	echo "</div>";
}

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;
}

Output

When user click the "Add to cart" button.

Go to the cart page by clicking the "Cart" option on the navigation bar.

How to update cart?

Update cart quantity with JavaScript

We have the 'update' button on cart.php file. When that button was clicked, a javascript code is triggered.

Place the following code inside $(document).ready(function(){ of layout_footer.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;
});

PHP script to update cart

The previous section will not work without this file.

Create update_quantity.php file. Place the following code and save it.

<?php
session_start();

// get the product id
$id = isset($_GET['id']) ? $_GET['id'] : 1;
$quantity = isset($_GET['quantity']) ? $_GET['quantity'] : "";

// make quantity a minimum of 1
$quantity=$quantity<=0 ? 1 : $quantity;

// remove the item from the array
unset($_SESSION['cart'][$id]);

// add the item with updated quantity
$_SESSION['cart'][$id]=array(
	'quantity'=>$quantity
);

// redirect to product list and tell the user it was added to cart
header('Location: cart.php?action=quantity_updated&id=' . $id);
?>

How to remove product on cart?

We have the 'remove' button on cart.php file. When that button was clicked, it will trigger remove_from_cart.php file.

Create remove_from_cart.php file. Place the following code and save it.

<?php
// start session
session_start();

// get the product id
$id = isset($_GET['id']) ? $_GET['id'] : "";
$name = isset($_GET['name']) ? $_GET['name'] : "";

// remove the item from the array
unset($_SESSION['cart'][$id]);

// redirect to product list and tell the user it was added to cart
header('Location: cart.php?action=removed&id=' . $id);
?>

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
// start session
session_start();

// connect to database
include 'config/database.php';

// include objects
include_once "objects/product.php";
include_once "objects/product_image.php";

// get database connection
$database = new Database();
$db = $database->getConnection();

// initialize objects
$product = new Product($db);
$product_image = new ProductImage($db);

// set page title
$page_title="Checkout";

// include page header html
include 'layout_header.php';

if(count($_SESSION['cart'])>0){

	// get the product ids
	$ids = array();
	foreach($_SESSION['cart'] as $id=>$value){
		array_push($ids, $id);
	}

	$stmt=$product->readByIds($ids);

	$total=0;
	$item_count=0;

	while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
        extract($row);

		$quantity=$_SESSION['cart'][$id]['quantity'];
		$sub_total=$price*$quantity;

		//echo "<div class='product-id' style='display:none;'>{$id}</div>";
		//echo "<div class='product-name'>{$name}</div>";

		// =================
		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-8'></div>";
	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_footer.php';
?>

Create place_order.php

We'll use this file to show a "thank you" message and remove all items in the cart.

Create place_order.php file. Place the following code.

<?php
// start session
session_start();

// remove items from the cart
session_destroy();

// set page title
$page_title="Thank You!";

// include page header HTML
include_once 'layout_header.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_footer.php';
?>

Output

When user click the "Update" button in the cart page.

If user click the "Delete" button.

The checkout page.

When user click the "Place Order" button.

How to make the product page?

Create product.php

Create product.php with the following basic code.

<?php
// start session
session_start();

// include classes
include_once "config/database.php";
include_once "objects/product.php";
include_once "objects/product_image.php";

// get database connection
$database = new Database();
$db = $database->getConnection();

// initialize objects
$product = new Product($db);
$product_image = new ProductImage($db);

// include page header HTML
include_once 'layout_header.php';

// content will be here

// include page footer HTML
include_once 'layout_footer.php';
?>

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
$id = isset($_GET['id']) ? $_GET['id'] : die('ERROR: missing ID.');

// set the id as product id property
$product->id = $id;

// to read single record product
$product->readOne();

// set page title
$page_title = $product->name;

// product thumbnail will be here

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'];
}

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. 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>";

// product image will be here

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;
}

Only one product image are displayed at a time. This part displays the larger product image based on the hovered product thumbnail.

Open product.php file. Replace // product image will be here comment with the following 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>";

// product details will be here

Make image hover work

Put the following jQuery code inside "$(document).ready(function(){" of layout_footer.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();
});

Display product details

This part display product price, description and category.

Open product.php file. Replace // product details will be here comment with the following 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>";

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'>";

	// if product was already added in the cart
	if(array_key_exists($id, $_SESSION['cart'])){
		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>";

			echo "<div class='m-b-10px f-w-b'>Quantity:</div>";
			echo "<input type='number' value='1' class='form-control m-b-10px cart-quantity' 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>";

Output

When user click on any product image in products.php page, he will land to a product page that looks like the image below.


If user hovers on any of those thumbnail or small images, the big image will change as well. The "Add to cart" button is working as well.

Here's the output when the product is already added to cart.

If user click the "Update Cart" button, he will land on the cart page where he can update the cart quantity.

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 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

How to run the source code?

We highly recommend for you to follow and study our well-detailed, step-by-step tutorial above first. Nothing beats experience when it comes to learning.

But we believe you will learn faster if you’ll see the final source code as well. We consider it as your additional guide.

Imagine the value or skill upgrade it can bring you. The additional income you can get from your work, projects or business. The precious time you save. Isn’t that what you want?

By now, you need to download our source codes. To do it, use any download buttons in the next few sections below.

Once you downloaded the source codes, here’s how you can run it.

  1. Extract the files to your server directory.
  2. Go to your PhpMyAdmin, create a database with a name "shop_cart_sessions_1".
  3. Import the "shop_cart_sessions_1.sql" file located in the "README" folder.
  4. You might need to change database credentials in /config/database.php
  5. Run "products.php", this is the main PHP file. We do not have index.php

Download the LEVEL 1 Source Code

FEATURE LEVEL 1
Learn to code a simple cart function YES
List all products from MySQL database YES
Pagination on products list page YES
Add to cart action button YES
Remove from cart action button Yes
Update cart quantity YES
Checkout Page YES
Place order / Thank you page YES
Amazon-style product details page YES
Change image on hover of thumbnail 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
PDO extension used YES
Step by step tutorial YES
Free source code updates YES
Free support for 6 months YES
$20 - Download now

Download the LEVEL 2 Source Code

FEATURE LEVEL 2
All features of LEVEL 1 source code 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
Quantity drop down options based on available stock YES
Well formatted money value YES
Check out button with cart icon YES
Product image viwable in lightbox YES
Shows number of stock left YES
Stock decreases once checked out YES
Order saved in orders and order_items table in the database YES
Emtpy cart button YES
Emtpy cart confirmation pop up YES
Bootstrap enabled UI YES
Cart page that lists all products added to cart YES
Quantity text box beside update quantity button YES
Show price, category and stocks left in product list page 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
$40 - Download now

PHP Shopping Cart Module

You can download our "PHP Shopping Cart & Ordering Module" source code. It has several features you need to learn more about how to handle the users, shopping cart, and ordering using the PHP & MySQL technology. CLICK HERE TO LEARN MORE

PHP Shopping Cart System

You can download our "PHP Shopping Cart System" source code as well. Many of you requested this type of source code and not it is here!

You needed a shopping cart system with user management (merchant and customer), product management, order management, security and more features based on our source codes here in codeofaninja.com. CLICK HERE TO LEARN MORE.

What's Next?

You have two options:

Option #1:
We just learned how to code an online shopping cart from scratch using PHP SESSIONS. But did you know that we can create the almost the same functions using another PHP mechanism called COOKIES?

If you're excited to learn this new concept, let us go to the next tutorial: PHP Shopping Cart Tutorial Using COOKIES

Option #2:
This next tutorial is the start of our JavaScript programming journey. Go to our next tutorial: How To Create a Simple REST API in PHP – Step By Step Guide!

Related Tutorials

Please explore more tutorials on our start page. Click here.

Some Notes

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.

Subscribe to CodeOfaNinja

We constantly improve CodeOfaNinja. We update our tutorials and source codes. Receive valuable web programming tutorials and updates to your email. Subscribe now!

Enjoy high-quality web programming tutorials.
Subscribe to CodeOfaNinja now for FREE!

Thank You!

Thank you for studying our tutorial about PHP Shopping Cart Tutorial using SESSIONS!