Shopping Cart is a vital part of every e-commerce application that allows the user to select items for purchase. It helps online customers to purchase multiple items at once. Upon checkout, the shopping cart calculates the total amount for the order, handles the shipping, and shows the order preview. The main challenge of e-commerce website development is shopping cart implementation.
The SESSION is used to build shopping cart in PHP. If your application is developed with CodeIgniter, a shopping cart can be easily integrated with Cart Class. CodeIgniter provides Cart library that helps to integrate shopping cart functionality in the CodeIgniter framework. In this tutorial, we will show you how to implement shopping cart in CodeIgniter.
This shopping cart tutorial demonstrates the cart and checkout process in CodeIgniter 3 application. In the example script, the CodeIgniter Cart library will be used to implement core cart functionality. Also, the customer and order information will be stored in the MySQL database.
Before getting started, take a look at the file structure of the CodeIgniter Shopping Cart.
codeigniter_shopping_cart/ ├── application/ │ ├── controllers/ │ │ ├── Products.php │ │ ├── Cart.php │ │ └── Checkout.php │ ├── models/ │ │ └── Product.php │ └── views/ │ ├── products/ │ │ └── index.php │ ├── cart/ │ │ └── index.php │ └── checkout/ │ ├── index.php │ └── order-success.php ├── uploads/ │ └── product_images/ └── assets/ ├── css/ │ ├── bootstrap.min.css │ └── style.css └── js/ └── jquery.min.js
To store the products, customers, and orders information, some tables need to be created in the database.
The following SQL creates a products
table in the MySQL database.
CREATE TABLE `products` ( `id` int(11) NOT NULL AUTO_INCREMENT, `image` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `description` text COLLATE utf8_unicode_ci NOT NULL, `price` float(10,2) NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1' COMMENT '1=Active | 0=Inactive', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The following SQL creates a customers
table in the MySQL database.
CREATE TABLE `customers` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(50) COLLATE utf8_unicode_ci NOT NULL, `phone` varchar(15) COLLATE utf8_unicode_ci NOT NULL, `address` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1' COMMENT '1=Active | 0=Inactive', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The following SQL creates a orders
table in the MySQL database.
CREATE TABLE `orders` ( `id` int(11) NOT NULL AUTO_INCREMENT, `customer_id` int(11) NOT NULL, `grand_total` float(10,2) NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1' COMMENT '1=Active | 0=Inactive', PRIMARY KEY (`id`), KEY `customer_id` (`customer_id`), CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The following SQL creates an order_items
table in the MySQL database.
CREATE TABLE `order_items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order_id` int(11) NOT NULL, `product_id` int(11) NOT NULL, `quantity` int(5) NOT NULL, `sub_total` float(10,2) NOT NULL, PRIMARY KEY (`id`), KEY `order_id` (`order_id`), CONSTRAINT `order_items_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
autoload.php
Specify some useful library and helper to loaded by default.
$autoload['libraries'] = array('database', 'session');
$autoload['helper'] = array('url');
The following controllers are used to handle the shopping cart, checkout, and order submission process.
1. Products.php
The Products controller handles the product listing and Add to Cart functionality.
getRows()
function of Product model.insert()
method of Cart class.<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Products extends CI_Controller{
function __construct(){
parent::__construct();
// Load cart library
$this->load->library('cart');
// Load product model
$this->load->model('product');
}
function index(){
$data = array();
// Fetch products from the database
$data['products'] = $this->product->getRows();
// Load the product list view
$this->load->view('products/index', $data);
}
function addToCart($proID){
// Fetch specific product by ID
$product = $this->product->getRows($proID);
// Add product to the cart
$data = array(
'id' => $product['id'],
'qty' => 1,
'price' => $product['price'],
'name' => $product['name'],
'image' => $product['image']
);
$this->cart->insert($data);
// Redirect to the cart page
redirect('cart/');
}
}
2. Cart.php
The Cart controller handles the shopping cart functionality.
contents()
method of Cart class.update()
method of Cart class. remove()
method of Cart class.<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Cart extends CI_Controller{
function __construct(){
parent::__construct();
// Load cart library
$this->load->library('cart');
// Load product model
$this->load->model('product');
}
function index(){
$data = array();
// Retrieve cart data from the session
$data['cartItems'] = $this->cart->contents();
// Load the cart view
$this->load->view('cart/index', $data);
}
function updateItemQty(){
$update = 0;
// Get cart item info
$rowid = $this->input->get('rowid');
$qty = $this->input->get('qty');
// Update item in the cart
if(!empty($rowid) && !empty($qty)){
$data = array(
'rowid' => $rowid,
'qty' => $qty
);
$update = $this->cart->update($data);
}
// Return response
echo $update?'ok':'err';
}
function removeItem($rowid){
// Remove item from cart
$remove = $this->cart->remove($rowid);
// Redirect to the cart page
redirect('cart/');
}
}
3. Checkout.php
The Checkout controller handles the order submission process.
placeOrder()
function.contents()
method of Cart class.destroy()
method of Cart class.<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Checkout extends CI_Controller{
function __construct(){
parent::__construct();
// Load form library & helper
$this->load->library('form_validation');
$this->load->helper('form');
// Load cart library
$this->load->library('cart');
// Load product model
$this->load->model('product');
$this->controller = 'checkout';
}
function index(){
// Redirect if the cart is empty
if($this->cart->total_items() <= 0){
redirect('products/');
}
$custData = $data = array();
// If order request is submitted
$submit = $this->input->post('placeOrder');
if(isset($submit)){
// Form field validation rules
$this->form_validation->set_rules('name', 'Name', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email');
$this->form_validation->set_rules('phone', 'Phone', 'required');
$this->form_validation->set_rules('address', 'Address', 'required');
// Prepare customer data
$custData = array(
'name' => strip_tags($this->input->post('name')),
'email' => strip_tags($this->input->post('email')),
'phone' => strip_tags($this->input->post('phone')),
'address'=> strip_tags($this->input->post('address'))
);
// Validate submitted form data
if($this->form_validation->run() == true){
// Insert customer data
$insert = $this->product->insertCustomer($custData);
// Check customer data insert status
if($insert){
// Insert order
$order = $this->placeOrder($insert);
// If the order submission is successful
if($order){
$this->session->set_userdata('success_msg', 'Order placed successfully.');
redirect($this->controller.'/orderSuccess/'.$order);
}else{
$data['error_msg'] = 'Order submission failed, please try again.';
}
}else{
$data['error_msg'] = 'Some problems occured, please try again.';
}
}
}
// Customer data
$data['custData'] = $custData;
// Retrieve cart data from the session
$data['cartItems'] = $this->cart->contents();
// Pass products data to the view
$this->load->view($this->controller.'/index', $data);
}
function placeOrder($custID){
// Insert order data
$ordData = array(
'customer_id' => $custID,
'grand_total' => $this->cart->total()
);
$insertOrder = $this->product->insertOrder($ordData);
if($insertOrder){
// Retrieve cart data from the session
$cartItems = $this->cart->contents();
// Cart items
$ordItemData = array();
$i=0;
foreach($cartItems as $item){
$ordItemData[$i]['order_id'] = $insertOrder;
$ordItemData[$i]['product_id'] = $item['id'];
$ordItemData[$i]['quantity'] = $item['qty'];
$ordItemData[$i]['sub_total'] = $item["subtotal"];
$i++;
}
if(!empty($ordItemData)){
// Insert order items
$insertOrderItems = $this->product->insertOrderItems($ordItemData);
if($insertOrderItems){
// Remove items from the cart
$this->cart->destroy();
// Return order ID
return $insertOrder;
}
}
}
return false;
}
function orderSuccess($ordID){
// Fetch order data from the database
$data['order'] = $this->product->getOrder($ordID);
// Load order details view
$this->load->view($this->controller.'/order-success', $data);
}
}
The Product model handles the database related operations (Fetch and Insert).
orders
table based on the ID.customers
table.orders
table.order_items
table.<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Product extends CI_Model{
function __construct() {
$this->proTable = 'products';
$this->custTable = 'customers';
$this->ordTable = 'orders';
$this->ordItemsTable = 'order_items';
}
/*
* Fetch products data from the database
* @param id returns a single record if specified, otherwise all records
*/
public function getRows($id = ''){
$this->db->select('*');
$this->db->from($this->proTable);
$this->db->where('status', '1');
if($id){
$this->db->where('id', $id);
$query = $this->db->get();
$result = $query->row_array();
}else{
$this->db->order_by('name', 'asc');
$query = $this->db->get();
$result = $query->result_array();
}
// Return fetched data
return !empty($result)?$result:false;
}
/*
* Fetch order data from the database
* @param id returns a single record of the specified ID
*/
public function getOrder($id){
$this->db->select('o.*, c.name, c.email, c.phone, c.address');
$this->db->from($this->ordTable.' as o');
$this->db->join($this->custTable.' as c', 'c.id = o.customer_id', 'left');
$this->db->where('o.id', $id);
$query = $this->db->get();
$result = $query->row_array();
// Get order items
$this->db->select('i.*, p.image, p.name, p.price');
$this->db->from($this->ordItemsTable.' as i');
$this->db->join($this->proTable.' as p', 'p.id = i.product_id', 'left');
$this->db->where('i.order_id', $id);
$query2 = $this->db->get();
$result['items'] = ($query2->num_rows() > 0)?$query2->result_array():array();
// Return fetched data
return !empty($result)?$result:false;
}
/*
* Insert customer data in the database
* @param data array
*/
public function insertCustomer($data){
// Add created and modified date if not included
if(!array_key_exists("created", $data)){
$data['created'] = date("Y-m-d H:i:s");
}
if(!array_key_exists("modified", $data)){
$data['modified'] = date("Y-m-d H:i:s");
}
// Insert customer data
$insert = $this->db->insert($this->custTable, $data);
// Return the status
return $insert?$this->db->insert_id():false;
}
/*
* Insert order data in the database
* @param data array
*/
public function insertOrder($data){
// Add created and modified date if not included
if(!array_key_exists("created", $data)){
$data['created'] = date("Y-m-d H:i:s");
}
if(!array_key_exists("modified", $data)){
$data['modified'] = date("Y-m-d H:i:s");
}
// Insert order data
$insert = $this->db->insert($this->ordTable, $data);
// Return the status
return $insert?$this->db->insert_id():false;
}
/*
* Insert order items data in the database
* @param data array
*/
public function insertOrderItems($data = array()) {
// Insert order items
$insert = $this->db->insert_batch($this->ordItemsTable, $data);
// Return the status
return $insert?true:false;
}
}
1. products/index.php
:
The products are listed with Add to Cart button. Also, the total number of items of the cart is shown using total_items()
method of Cart library.
<h2>PRODUCTS</h2>
<!-- Cart basket -->
<div class="cart-view">
<a href="<?php echo base_url('cart'); ?>" title="View Cart"><i class="icart"></i> (<?php echo ($this->cart->total_items() > 0)?$this->cart->total_items().' Items':'Empty'; ?>)</a>
</div>
<!-- List all products -->
<div class="row col-lg-12">
<?php if(!empty($products)){ foreach($products as $row){ ?>
<div class="card col-lg-3">
<img class="card-img-top" src="<?php echo base_url('uploads/product_images/'.$row['image']); ?>" alt="">
<div class="card-body">
<h5 class="card-title"><?php echo $row["name"]; ?></h5>
<h6 class="card-subtitle mb-2 text-muted">Price: <?php echo '$'.$row["price"].' USD'; ?></h6>
<p class="card-text"><?php echo $row["description"]; ?></p>
<a href="<?php echo base_url('products/addToCart/'.$row['id']); ?>" class="btn btn-primary">Add to Cart</a>
</div>
</div>
<?php } }else{ ?>
<p>Product(s) not found...</p>
<?php } ?>
</div>
2. cart/index.php
:
This view displays the shopping cart with products and price details.
updateCartItem()
function initiate an Ajax request to update the quantity of the item using jQuery. The rowid and quantity are sent via Ajax to the updateItemQty()
method of Cart controller.<!-- Include jQuery library -->
<script src="<?php echo base_url('assets/js/jquery.min.js'); ?>"></script>
<script>
// Update item quantity
function updateCartItem(obj, rowid){
$.get("<?php echo base_url('cart/updateItemQty/'); ?>", {rowid:rowid, qty:obj.value}, function(resp){
if(resp == 'ok'){
location.reload();
}else{
alert('Cart update failed, please try again.');
}
});
}
</script>
<h1>SHOPPING CART</h1>
<table class="table table-striped">
<thead>
<tr>
<th width="10%"></th>
<th width="30%">Product</th>
<th width="15%">Price</th>
<th width="13%">Quantity</th>
<th width="20%" class="text-right">Subtotal</th>
<th width="12%"></th>
</tr>
</thead>
<tbody>
<?php if($this->cart->total_items() > 0){ foreach($cartItems as $item){ ?>
<tr>
<td>
<?php $imageURL = !empty($item["image"])?base_url('uploads/product_images/'.$item["image"]):base_url('assets/images/pro-demo-img.jpeg'); ?>
<img src="<?php echo $imageURL; ?>" width="50"/>
</td>
<td><?php echo $item["name"]; ?></td>
<td><?php echo '$'.$item["price"].' USD'; ?></td>
<td><input type="number" class="form-control text-center" value="<?php echo $item["qty"]; ?>" onchange="updateCartItem(this, '<?php echo $item["rowid"]; ?>')"></td>
<td class="text-right"><?php echo '$'.$item["subtotal"].' USD'; ?></td>
<td class="text-right"><button class="btn btn-sm btn-danger" onclick="return confirm('Are you sure to delete item?')?window.location.href='<?php echo base_url('cart/removeItem/'.$item["rowid"]); ?>':false;"><i class="itrash"></i> </button> </td>
</tr>
<?php } }else{ ?>
<tr><td colspan="6"><p>Your cart is empty.....</p></td>
<?php } ?>
<?php if($this->cart->total_items() > 0){ ?>
<tr>
<td></td>
<td></td>
<td></td>
<td><strong>Cart Total</strong></td>
<td class="text-right"><strong><?php echo '$'.$this->cart->total().' USD'; ?></strong></td>
<td></td>
</tr>
<?php } ?>
</tbody>
</table>
3. checkout/:
3.1. index.php
This view displays the preview of the order before submission.
<h1>CHECKOUT</h1>
<div class="checkout">
<div class="row">
<?php if(!empty($error_msg)){ ?>
<div class="col-md-12">
<div class="alert alert-danger"><?php echo $error_msg; ?></div>
</div>
<?php } ?>
<div class="col-md-4 order-md-2 mb-4">
<h4 class="d-flex justify-content-between align-items-center mb-3">
<span class="text-muted">Your Cart</span>
<span class="badge badge-secondary badge-pill"><?php echo $this->cart->total_items(); ?></span>
</h4>
<ul class="list-group mb-3">
<?php if($this->cart->total_items() > 0){ foreach($cartItems as $item){ ?>
<li class="list-group-item d-flex justify-content-between lh-condensed">
<div>
<?php $imageURL = !empty($item["image"])?base_url('uploads/product_images/'.$item["image"]):base_url('assets/images/pro-demo-img.jpeg'); ?>
<img src="<?php echo $imageURL; ?>" width="75"/>
<h6 class="my-0"><?php echo $item["name"]; ?></h6>
<small class="text-muted"><?php echo '$'.$item["price"]; ?>(<?php echo $item["qty"]; ?>)</small>
</div>
<span class="text-muted"><?php echo '$'.$item["subtotal"]; ?></span>
</li>
<?php } }else{ ?>
<li class="list-group-item d-flex justify-content-between lh-condensed">
<p>No items in your cart...</p>
</li>
<?php } ?>
<li class="list-group-item d-flex justify-content-between">
<span>Total (USD)</span>
<strong><?php echo '$'.$this->cart->total(); ?></strong>
</li>
</ul>
<a href="<?php echo base_url('products/'); ?>" class="btn btn-block btn-info">Add Items</a>
</div>
<div class="col-md-8 order-md-1">
<h4 class="mb-3">Contact Details</h4>
<form method="post">
<div class="mb-3">
<label for="name">Name</label>
<input type="text" class="form-control" name="name" value="<?php echo !empty($custData['name'])?$custData['name']:''; ?>" placeholder="Enter name" required>
<?php echo form_error('name','<p class="help-block error">','</p>'); ?>
</div>
<div class="mb-3">
<label for="email">Email</label>
<input type="email" class="form-control" name="email" value="<?php echo !empty($custData['email'])?$custData['email']:''; ?>" placeholder="Enter email" required>
<?php echo form_error('email','<p class="help-block error">','</p>'); ?>
</div>
<div class="mb-3">
<label for="phone">Phone</label>
<input type="text" class="form-control" name="phone" value="<?php echo !empty($custData['phone'])?$custData['phone']:''; ?>" placeholder="Enter contact no" required>
<?php echo form_error('phone','<p class="help-block error">','</p>'); ?>
</div>
<div class="mb-3">
<label for="address">Address</label>
<input type="text" class="form-control" name="address" value="<?php echo !empty($custData['address'])?$custData['address']:''; ?>" placeholder="Enter address" required>
<?php echo form_error('address','<p class="help-block error">','</p>'); ?>
</div>
<input class="btn btn-success btn-lg btn-block" type="submit" name="placeOrder" value="Place Order">
</form>
</div>
</div>
</div>
3.2. order-success.php
If the order submission is successful, the status is shown with the order details.
<h1>ORDER STATUS</h1>
<?php if(!empty($order)){ ?>
<div class="col-md-12">
<div class="alert alert-success">Your order has been placed successfully.</div>
</div>
<!-- Order status & shipping info -->
<div class="row col-lg-12 ord-addr-info">
<div class="hdr">Order Info</div>
<p><b>Reference ID:</b> #<?php echo $order['id']; ?></p>
<p><b>Total:</b> <?php echo '$'.$order['grand_total'].' USD'; ?></p>
<p><b>Placed On:</b> <?php echo $order['created']; ?></p>
<p><b>Buyer Name:</b> <?php echo $order['name']; ?></p>
<p><b>Email:</b> <?php echo $order['email']; ?></p>
<p><b>Phone:</b> <?php echo $order['phone']; ?></p>
</div>
<!-- Order items -->
<div class="row col-lg-12">
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th>Product</th>
<th>Price</th>
<th>QTY</th>
<th>Sub Total</th>
</tr>
</thead>
<tbody>
<?php
if(!empty($order['items'])){
foreach($order['items'] as $item){
?>
<tr>
<td>
<?php $imageURL = !empty($item["image"])?base_url('uploads/product_images/'.$item["image"]):base_url('assets/images/pro-demo-img.jpeg'); ?>
<img src="<?php echo $imageURL; ?>" width="75"/>
</td>
<td><?php echo $item["name"]; ?></td>
<td><?php echo '$'.$item["price"].' USD'; ?></td>
<td><?php echo $item["quantity"]; ?></td>
<td><?php echo '$'.$item["sub_total"].' USD'; ?></td>
</tr>
<?php }
} ?>
</tbody>
</table>
</div>
<?php } }else{ ?>
<div class="col-md-12">
<div class="alert alert-danger">Your order submission failed.</div>
</div>
<?php } ?>
PayPal Payment Gateway Integration in CodeIgniter
We have tried to cover the entire process to implement shopping cart functionality in the CodeIgniter application. You can easily enhance this script and integrate advanced functionality as per your needs. Our example code allows you to add shopping cart instantly in CodeIgniter framework. In this example, Bootstrap library is used to style the view of the product list, shopping cart, checkout, and order.
Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request
Hello and thank you for this awesome tutorial
one thing i am trying to achieve is to not refresh the page with reload but instead by using ajax and update only the current view.
I have not been able to achieve that yet.
Your guidance will be appreciated.
Thank you
Nice example and easy to understand. Thank you.
I will change the way the orders are retrieved for the success page in checkout controller, because visitors can supply any order number and view others people orders in the current implementation.
Thank you for this code.
your training has helped me a lot.