PHP Code – Shopping Cart System Tutorial using Sessions

If you want to build your own online shopping cart from scratch, this post can help you get it done because today, we are building a simple website with shopping cart using PHP and MySQL. I also assume you already know something about PHP sessions.

A lot of people uses a ready-made software for this. But for coders like us, it is important to know how it was done so that we can create more features like making the system more secured, add some unique functionality, etc.

Our simple system will have three pages.

Home Page – the landing page, you can also show your products here, but in our example, we will just display a welcome message.

Products Page – shows your list of products with the option “add to cart” – cart icon with plus (+) sign.

Cart Page – shows the list of products the user added to his cart. It has the option to “remove from cart ” – cart icon with dash (-) sign.

DOWNLOAD CODE | LIVE DEMO

Our post will cover the following contents:

1.0 Preparing Our Database
2.0 Navigation
3.0 Welcoming Online Shoppers
4.0 Listing Your Products
5.0 Adding Products To Cart
6.0 Listing Products in the Cart
7.0 Removing Products From Cart
8.0 Styling Our Online Shop

1.0 Preparing our Database

SQL table we used.

CREATE TABLE IF NOT EXISTS `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `price` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

--
-- Dumping data for table `products`
--

INSERT INTO `products` (`id`, `name`, `price`) VALUES
(1, 'LG P880 4X HD', 336),
(2, 'Google Nexus 4', 299),
(3, 'Samsung Galaxy S4', 600);

libs/DbConnect.php – will help us connect to the database.

2.0 Navigation

Navigation.php – contains the nagivation links to the home, products and cart page. This file is included to the main sections of our system.

<?php
// if session 'cart' was set, count it, else set it to 0
$cartItemCount = isset($_SESSION['cart']) ? count($_SESSION['cart']) : 0;
?>
<div class='navigation'>
    <a href='index.php' class='customButton'>Home</a>
    <a href='Products.php' class='customButton'>View Products</a>
    <a href='Cart.php' class='customButton'>View Cart <?php echo "({$cartItemCount})"; ?></a>
</div>

3.0 Welcoming Online Shoppers

Index.php – your customers or online shoppers should feel welcome to your site. I don’t know how you design this but the code below is just a very simple example.

<?php
session_start();
?>
<!DOCTYPE HTML>
<html>
    <head>
        <title>php shopping cart tutorial - home - codeofaninja.com</title>
        <link type="text/css" rel="stylesheet" href="css/style.css" />
    </head>
<body>

<div class='sectionContainer'>
    <div class='sectionHeader'>Home</div>
    <?php 
        // this will make 'home', 'view products' and 'view cart' appear
        include 'Navigation.php' 
    ?>
    
    <div class='sectionContents'>
        Welcome to Mike's shopping website!
    </div>
</div>

</body>
</html>

4.0 Listing Your Products

Products.php – lists products from our database.

<?php
session_start();
?>
<!DOCTYPE HTML>
<html>
    <head>
        <title>php shopping cart tutorial - products - codeofaninja.com</title>
        <link type="text/css" rel="stylesheet" href="css/style.css" />
    </head>
<body>

<div class='sectionContainer'>
    <div class='sectionHeader'>Products</div>
    <?php 
        // this will make 'home', 'view products' and 'view cart' appear
        include 'Navigation.php' 
    ?>
    
    <div class='sectionContents'>
    
<?php
// to prevent undefined index notice
$action = isset($_GET['action']) ? $_GET['action'] : "";
$name = isset($_GET['name']) ? $_GET['name'] : "";

if($action=='add'){
    echo "<div>" . $name . " was added to your cart.</div>";
}

if($action=='exists'){
    echo "<div>" . $name . " already exists in your cart.</div>";
}

require "libs/DbConnect.php";

$query = "SELECT id, name, price FROM products";
$stmt = $con->prepare( $query );
$stmt->execute();

$num = $stmt->rowCount();

if($num>0){
    echo "<table border='0'>";//start table
    
        // our table heading
        echo "<tr>";
            echo "<th class='textAlignLeft'>Product Name</th>";
            echo "<th>Price (USD)</th>";
            echo "<th>Action</th>";
        echo "</tr>";
        
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
            extract($row);
            
            //creating new table row per record
            echo "<tr>";
                echo "<td>{$name}</td>";
                echo "<td class='textAlignRight'>{$price}</td>";
                echo "<td class='textAlignCenter'>";
                    echo "<a href='addToCart.php?id={$id}&name={$name}' class='customButton'>";
                        echo "<img src='images/add-to-cart.png' title='Add To Cart' />";
                    echo "</a>";
                echo "</td>";
            echo "</tr>";
        }
        
    echo "</table>";
}

// no products in the database
else{
    echo "No products found.";
}
?>
    </div>
</div>

</body>
</html>

5.0 Adding Products To Cart

AddToCart.php – adds the product ID to the ‘cart’ session array. It also checks if the ID is already added in the session to prevent duplicate products in the cart. This file is triggered when the user clicked the ‘add to cart’ icon.

<?php
session_start();

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

/* 
 * 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(in_array($id, $_SESSION['cart'])){
    // redirect to product list and tell the user it was added to cart
    header('Location: Products.php?action=exists&id' . $id . '&name=' . $name);
}

// else, add the item to the array
else{
    array_push($_SESSION['cart'], $id);
    
    // redirect to product list and tell the user it was added to cart
    header('Location: Products.php?action=add&id' . $id . '&name=' . $name);
}

?>

6.0 Listing Products in the Cart

Cart.php – lists products added to the users’ cart.

<?php
session_start();
?>
<!DOCTYPE HTML>
<html>
    <head>
        <title>php shopping cart tutorial - cart - codeofaninja.com</title>
        <link type="text/css" rel="stylesheet" href="css/style.css" />
    </head>
<body>

<div class='sectionContainer'>
    <div class='sectionHeader'>Shopping Cart</div>
    <?php 
        // this will make 'home', 'view products' and 'view cart' appear
        include 'Navigation.php' 
    ?>
    
    <div class='sectionContents'>
    <?php
    $action = isset($_GET['action']) ? $_GET['action'] : "";
    
    if($action=='removed'){
        echo "<div>" . $_GET['name'] . " was removed from cart.</div>";
    }
    
    if(isset($_SESSION['cart'])){
        $ids = "";
        foreach($_SESSION['cart'] as $id){
            $ids = $ids . $id . ",";
        }
        
        // remove the last comma
        $ids = rtrim($ids, ',');
        
        require "libs/DbConnect.php";

        $query = "SELECT id, name, price FROM products WHERE id IN ({$ids})";
        $stmt = $con->prepare( $query );
        $stmt->execute();

        $num = $stmt->rowCount();

        if($num>0){
            echo "<table border='0'>";//start table
            
                // our table heading
                echo "<tr>";
                    echo "<th class='textAlignLeft'>Product Name</th>";
                    echo "<th>Price (USD)</th>";
                    echo "<th>Action</th>";
                echo "</tr>";
                
                //also compute for total price
                $totalPrice = 0;
                
                while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
                    extract($row);
                    
                    $totalPrice += $price;
                    
                    //creating new table row per record
                    echo "<tr>";
                        echo "<td>{$name}</td>";
                        echo "<td class='textAlignRight'>{$price}</td>";
                        echo "<td class='textAlignCenter'>";
                            echo "<a href='removeFromCart.php?id={$id}&name={$name}' class='customButton'>";
                                echo "<img src='images/remove-from-cart.png' title='Remove from cart' />";
                            echo "</a>";
                        echo "</td>";
                    echo "</tr>";
                }
                
                echo "<tr>";
                    echo "<th class='textAlignCenter'>Total Price</th>";
                    echo "<th class='textAlignRight'>{$totalPrice}</th>";
                    echo "<th></th>";
                echo "</tr>";
                
            echo "</table>";
            echo "<br /><div><a href='#' class='customButton'>Checkout</a></div>";
        }else{
            echo "<div>No products found in your cart. :(</div>";
        }

    }else{
        echo "<div>No products in cart yet.</div>";
    }
    ?>
    </div>
</div>

</body>
</html>

7.0 Removing Products From Cart

RemoveFromCart.php – removes product ID the ‘cart’ session array. This file is triggered when the user clicked the ‘remove from cart’ icon.

<?php
session_start();

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

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

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

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

8.0 Styling Our Online Shop

css/style.css – to make our simple system user friendly.

body{
    font: 1em "Lucida Grande", Tahoma, Verdana, sans-serif;
    color: #404040;
}

.navigation{
    
    padding:1em;
}

.sectionContents{
    
    padding: 0 1em 1em 1em;
}

.sectionContents table{
    width:100%;
}

.sectionContents table th{
    padding:0.5em;
    background-color:#f3f3f3;
}

.sectionContents table td{
    padding:0.5em;
    background-color:#f3f3f3;
}

.sectionContainer{
    
    text-align:center;
    border:thin solid #000;
    width:30em;
    margin:7em auto 0 auto;
}

.sectionHeader{
    font-size:1.5em;
    border-bottom:thin solid gray;
    padding:10px;
    background:#f3f3f3;
}

.textAlignCenter{
    text-align:center;
}

.textAlignLeft{
    text-align:left;
}

.textAlignRight{
    text-align:right;
}

.customButton {
    padding:5px;
    -moz-box-shadow:inset 0px 1px 0px 0px #bbdaf7;
    -webkit-box-shadow:inset 0px 1px 0px 0px #bbdaf7;
    box-shadow:inset 0px 1px 0px 0px #bbdaf7;
    background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #79bbff), color-stop(1, #378de5) );
    background:-moz-linear-gradient( center top, #79bbff 5%, #378de5 100% );
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#79bbff', endColorstr='#378de5');
    background-color:#79bbff;
    -moz-border-radius:6px;
    -webkit-border-radius:6px;
    border-radius:6px;
    border:1px solid #84bbf3;
    display:inline-block;
    color:#ffffff;
    font-family:arial;
    font-size:15px;
    font-weight:bold;
    text-decoration:none;
    text-shadow:1px 1px 0px #528ecc;
    cursor:pointer;
}

.customButton:hover {
    background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #378de5), color-stop(1, #79bbff) );
    background:-moz-linear-gradient( center top, #378de5 5%, #79bbff 100% );
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#378de5', endColorstr='#79bbff');
    background-color:#378de5;
}

.customButton:active {
    position:relative;
    top:1px;
}

Please feel free to comment if you have any questions, suggestions, found something wrong or want to contribute to this code. :)

Notes: For those having problems about the $conn variable, I highly recommend learning about PHP CRUD first. It will help you a lot.

January 2014 Update: Some of you are having a hard time fixing the undefined index notice. I updated the code above and download link to help you fix it, please try it and tell us in the comments section if it works or not. Thanks!

The Code of a Ninja Resources

  • ninjaz

    How can one change the picture per table cell?

    • ninjazhai

      Hey @ninjaz, how about saving the image url to your database and later access it?

  • joe

    its helpful to me i did something…..but i also i need disabling code can i?
    thanx

    • ninjazhai

      HI @disqus_PxewpCMGPA:disqus, what exactly do you want to disable?

  • Mystro Odei

    hi it seems u didnt add the connection file to the zip file so some of the functions are not working. pls check that and by the way this is awesome work bigups.

    • ninjazhai

      hi @mystroodei:disqus, thanks for pointing it out, do you mean the DbConnect.php file?

      • Mystro Odei

        yes that exactly i think with that every bodies problem would be solved. thanks for your time

      • Mystro Odei

        please have you uploaded the Dbconnect.php already

  • Soujiro Seta

    I’ve got problem here Fatal error: Call to a member function prepare() on a non-object in C:xampphtdocsshopping-cartCart.php on line 39

  • drvipinlalt

    can you please help me… at last i want to add user name, phone number and add this whole things to database. any idea…

  • Carl Justin Guinto

    where is the codes for “(libs/DbConnect.php) ?

  • nicolous

    can you help for the codes of (libs/DbConnect.php) ?

  • nicolous

    would you help me about the (libs/DbConnect.php) ?
    pleasseeeeeeeeee :)

  • Ayane

    Can somebody tell me what tags and variables should i change in Products.php if im using this table, im confused due to variables using same names and dont know where exacly i should or shouldnt change the original variables for mine.

    CREATE TABLE Articulos(
    OID_A SMALLINT NOT NULL,
    Descripcion VARCHAR(200),
    Precio NUMBER(6,2),
    PRIMARY KEY(OID_A)
    ) ;

    OID_A instead of ‘id’
    Descripcion instead of ‘name’
    precio instead of ‘price’

    thnx

  • henry

    please what is the name of the db created in this tutorial for our table “product”?

    • ninjazhai

      Hey henry, you can put any name on your database, as long as the tables are almost the same with those above!

  • kirti tonk

    superb code…… :) very helpful….. :)

  • Kwabyna Nkrumah

    $con undefine.. please help me

  • ninjazhai

    Hey ron, you can do that with the help of this PHP login tutorial http://www.codeofaninja.com/2013/03/php-login-script.html

    • Jeremy

      I’d strongly recommend you do not save against a userid in the form of cookies, it’s a really bad idea if you aren’t encrypting your data and enforcing encryption.

      Use a randomly generated cart/session id for that purpose it’s really I hate to be blunt but it’s a massive security hole.

  • ninjazhai

    Hey thanks for your suggestions, I will update this post with those features!

  • lanner

    hello
    How to add the same product more than 1 time ?

    • ninjazhai

      Hey @lanner, currently, this code does not support changing product quantity…

  • su

    what is your database name?

    • ninjazhai

      Hey @su, my database name is called “sampledb”

  • Jeremy Smith

    Words can’t express how greatful 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!

    • ninjazhai

      Hello @disqus_Tkg3Hukomt:disqus, thanks for the kind words! Please don’t hesitate to share your comments regarding any article here so that it will keep on improving with the help of people like you! Thanks!

  • Jeremy

    Without wanting to cause any offence it does create a little bit of traffic between the client and the server, since with sessions you have to have a file on the server and the clients browser (cookie), your real best bet’s to use pure cookies, though with the likes of bandwidth increasing can be done of course using the above.

    • ninjazhai

      For those who are reading this, please see my other reply to Jeremy below.

  • Jeremy

    Also sorry I could not put this into my first post about why you should not use sessions, if there was a disk failure or for some reason someone was to remove all sessions from the sessions location (defined in the php.ini file) then the person viewing the cart all items would disappear, with the earlier example where someone was to remove the cookie files from the servers file system using just cookies and not sessions they wouldn’t disappear.

    The above’s probably the most critical reason really not to use sessions, but as tutorials go, this is a great potential example :)

    • ninjazhai

      Hello @Jeremy, you got some good points there, I really appreciate your effort to improve this post! Your comments are well detailed to be a starting point for new development and contains true arguments about the subject.

      WooCommerce was using PHP sessions for cart data before, but last year they changed it and are now using cookies. 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 here http://wordpress.org/plugins/woocommerce/changelog/

      I will have to create another post on how to use cookies to store cart data. Thanks again for bringing this to my attention!

      But still, as you said, the tutorial above is a great potential example for understanding how shopping carts work before, and still a good example for low traffic shopping website.

  • windy

    Notice: Undefined variable: id in C:xampphtdocsFish_fansPurchase.php on line 89
    line89 —> echo ““;

    what is the problem?
    T_T…help~~thanks

    • ninjazhai

      Hey @windy, are you sure you have a variable called $id in your code? It’s hard to debug since I can’t see your page source code..