Simple PHP Shopping Cart Tutorial

February 02, 2006 - 00:00

This is a very simple shopping cart that I wrote at university because many of my peers were asking for help with similar problems for assignments. It is incomplete and is not intended for use on a production website!

The shopping cart stores the product ids in an associative array, the keys are the product id and the values are the quantity of that particular product. To store information between pages we can use the \$_SESSION superglobal variable, by using an element of the array like this: \$_SESSION['cart'] - this is where our cart will be stored.

ID
Quantity
Stored Where?
1234
1
$_SESSION['cart'][1234]
1343
1
$_SESSION['cart'][1343]
3424
3
$_SESSION['cart'][3424]

Because we are going to use a session to store this cart we need to start the session at the very beginning of the page like this:

<?php session_start(); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

Notice how the function is before anything else, this includes whitespace.

Now lets define some operations that our cart will perform. Lets say we want the user to be able to add, remove and empty the cart. The script needs to know what the operation is and also, in the case of adding and removing, the id of the product.

We can tell the script this information as part of the URL for example /cart.php?action=add&id=1234

We need to be careful of SQL Injection attacks - so we must check that the product_id exists in our database, and also be sure that it is an integer, using the productExists function.

<?php

$product_id = $_GET['id']; //the product id from the URL
$action = $_GET['action']; //the action from the URL

//if there is an product_id and that product_id doesn't exist display an error message
if($product_id && !productExists($product_id)) {
    die("Error. Product Doesn't Exist");
}

switch($action) { //decide what to do

    case "add":
        $_SESSION['cart'][$product_id]++; //add one to the quantity of the product with id $product_id
    break;

    case "remove":
        $_SESSION['cart'][$product_id]--; //remove one from the quantity of the product with id $product_id
        if($_SESSION['cart'][$product_id] == 0) unset($_SESSION['cart'][$product_id]); //if the quantity is zero, remove it completely (using the 'unset' function) - otherwise is will show zero, then -1, -2 etc when the user keeps removing items.
    break;

    case "empty":
        unset($_SESSION['cart']); //unset the whole cart, i.e. empty the cart.
    break;

}

?>

 

Next we can show the user their shopping cart, by iterating through the cart items, using a foreach loop. But only if there is something in the cart, which is the reason for the 'if' statement:

<?php

if($_SESSION['cart']) { //if the cart isn't empty
//show the cart

    echo "<table border=\"1\" padding=\"3\" width=\"40%\">"; //format the cart using a HTML table

    //iterate through the cart, the $product_id is the key and $quantity is the value
    foreach($_SESSION['cart'] as $product_id => $quantity) {

        //get the name, description and price from the database - this will depend on your database implementation.
        //use sprintf to make sure that $product_id is inserted into the query as a number - to prevent SQL injection
        $sql = sprintf("SELECT name, description, price FROM php_shop_products WHERE id = %d;",
$product_id);

        $result = mysql_query($sql);

        //Only display the row if there is a product (though there should always be as we have already checked)
        if(mysql_num_rows($result) > 0) {

            list($name, $description, $price) = mysql_fetch_row($result);

            $line_cost = $price * $quantity; //work out the line cost
            $total = $total + $line_cost; //add to the total cost

            echo "<tr>";
            //show this information in table cells
            echo "<td align=\"center\">$name</td>";
            //along with a 'remove' link next to the quantity - which links to this page, but with an action of remove, and the id of the current product
            echo "<td align=\"center\">$quantity <a href=\"$_SERVER[PHP_SELF]?action=remove&id=$product_id\">X</a></td>";
            echo "<td align=\"center\">$line_cost</td>";

            echo "</tr>";

        }

    }

    //show the total
    echo "<tr>";
    echo "<td colspan=\"2\" align=\"right\">Total</td>";
    echo "<td align=\"right\">$total</td>";
    echo "</tr>";

    //show the empty cart link - which links to this page, but with an action of empty. A simple bit of javascript in the onlick event of the link asks the user for confirmation
    echo "<tr>";
    echo "<td colspan=\"3\" align=\"right\"><a href=\"$_SERVER[PHP_SELF]?action=empty\" onclick=\"return confirm('Are you sure?');\">Empty Cart</a></td>";
    echo "</tr>";
    echo "</table>";



}else{
//otherwise tell the user they have no items in their cart
    echo "You have no items in your shopping cart.";

}
?>

The productExists function takes a product_id as an argument, and returns true if it exists. It uses the sprintf function to insert the $product_id variable into the $sql variable as a number - to prevent SQL Injection.

//function to check if a product exists
function productExists($product_id) {
    //use sprintf to make sure that $product_id is inserted into the query as a number - to prevent SQL injection
    $sql = sprintf("SELECT * FROM php_shop_products WHERE id = %d;", $product_id);
    
    return mysql_num_rows(mysql_query($sql)) > 0;
}

Note This tutorial has been updated to prevent the SQL Injection security flaw describe here.

AttachmentSize
Plain text icon cart.txt4.3 KB
Plain text icon products.txt1.04 KB

Comments

Hannah's picture

awesome tutorial. thank you!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

1wayrocker's picture

Is there a check out feature for this? What I am looking for is to email the admin with the order upon clicking 'Check Out'.
Thanks!

Thomas Lewis's picture

Great tutorial, just one problem though.
I would like to have it so when I remove the last item in the cart (using the reduce case) instead of just leaving me with 0 rows showing and a "Total = 0" it emptys the cart completly.
Any help would be great.

James Hamilton's picture

The code here already does this? If the quantity of a product is zero the product in $_SESSION['cart'] is unset.

Anonymous's picture

I am using your script, and a nice script indeed. Only, I seen another version of this script almost the exact same as this one. This other script had an Update feature on the items in the cart to update the quantities. Is this possible with this script. I am kind of new to the world of PHP, but can understand concepts. I cant really write my own code entirely but can edit and understand how to alter established codes to make it work. Thanks

James Hamilton's picture

It is possible with some changes - this is just a basic cart. 

You'll need input boxes on the cart page and an update button. add the input boxes into the table loop giving them a name like "quantity_$id" where $id is the id of the product. then when you press submit you need to update the quantities stored in $_SESSION['cart'][$id] with the quantity variables in the $_POST array.

huzira's picture

hye James...
i noticed that most of the coding i found, will have the function to call the product such as below :

<?php
$sql = 'SELECT * FROM books ORDER BY id';
$result = $db->query($sql);
$output[] = '<ul>';
while ($row = $result->fetch()) {
$output[] = '<li>"'.$row['title'].'" by '.$row['author'].': &pound;'.$row['price'].'<br /><a href="cart.php?action=add&id='.$row['id'].'">Add to cart</a></li>';
}
$output[] = '</ul>';
echo join('',$output);
?>

how if, in my interfaces, i already have the list of the product and i just need the 'Add to Cart' function is working...for example, this is my coding...

<div class="gallery_box">
<div class="gb_left">
<a href="images/gallery/image_02_b.jpg" class="pirobox" title="Urea"><img src="images/urea.jpg" alt="2" /></a>
</div>
<div class="gb_right">

<h4>Urea </h4>
<p>50 KG = RM80.00 </p>
<div class="button"><a href="#">Add to Cart </a></div>
</div>
<div class="cleaner"></div>
</div>

i want that after user click the button, the item will be added to the cart...thanks in advance!

James Hamilton's picture

The "Add to Cart" URL needs the ID of the product which it refers too. That whole <div> should be inside a while loop like the first example you gave, which uses a list to display the products. Each time around the loop will output the next <div> with the next product info. Or if you're writing the HTML for the list manually then put the URL like cart.php?action=add&id=PRODUCT_ID where you manually put the PRODUCT_ID.

Huzira's picture

hye again james!!!

i got this error...

Notice: Use of undefined constant id - assumed 'id' in E:\xampp\htdocs\project\cart.php on line 32

Notice: Use of undefined constant action - assumed 'action' in E:\xampp\htdocs\project\cart.php on line 33

Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in E:\xampp\htdocs\project\cart.php on line 124

 Error. Product Doesn't Exist

line 32 :: $input_id = $_GET[id];     //the product id from the URL

line 33 :: $action = $_GET[action]; //the action from the URL

line 124 :: return mysql_num_rows(mysql_query($sql)) > 0;

and one more, how do i assign the id to my items? as you saw earlier, i use a manual list...thanks!! Laughing

James Hamilton's picture

I've fixed the code to stop the notices - id and action should have had single quotes around them.

If you're not using a database then you don't need the productExists function.

Add an id to the URL manually e.g. http://site.com/cart.php?action=add&id=1

However, I'd suggest you build an array of your products if you're not using a database, something like:

$products = array( array('id' => 1, 'name' => 'some product', 'price' => 5.99), array('id' => 2, 'name' => 'product 2', 'price' => 3.99) );

That way you can iterate through the array to generate the product list and also use the same data to get the product information for items in the cart.

Mike's picture

I have a problem with the function,

It says the product does not exist when i do "index.php?action=add&amp;id=32". Ive checked the database and there is infact a rom with id 32. The sql query that's beeing entered by this script does work. It just wont let me get past the "!productExists" function. Any idea what i am doing wrong ? I've really only copied everything from here and only changed the query value's accordingly to my database, ie id = game_id in mine.

Any help is welcome.

James Hamilton's picture

Not sure what the problem is without seeing your code. Are you sure the correct id is being inserted into SQL query? Can you print out the $sql variable to check?

Mike's picture

Im having a Fatal error:
Fatal error: Call to undefined function productExists() in C:\xampp\htdocs\dosfox\pages\main.php on line 23
This is line 23: if($product_id && !productexists($product_id)) {

Could anyone tell me what happend ?
I just copied and pasted the first bit of code into a php file.

Thx in advance

James Hamilton's picture

You need copy all of the code from the tutorial, including the code for the productExists function - see the end of the tutorial.

David Birkin's picture

This tutorial is extremely easy to follow, worked first time and is VERY easy to change to fit any design / requirement!

Thank you so much!

Sid's picture

hello,

Excellent tutorial you have here....its quite explanatory as well....thanks...

but a quick question.... I have added update_all case. The users have a textbox in which they can update the quantity of their items...and on hitting update_all button, it should update all the quantities... but it is only updating the last item's quantity in the cart.

can you tell me how do i achieve update all function here?

Thanks.

Anonymous's picture

This is a great tutorial. Classic asp is my background but Ive been dabbling in php. Im going to try your tutorial in my next mini php project. Keep up the good work.

Incidentally I did my BTEC in computer studies at Lewisham College in your neck of the woods and wanted to do a degree at Goldsmiths but never got round to it.
(Sorry about the email. Im shy I guess)

Add new comment