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!

AJAX CRUD Tutorial Using JavaScript, JSON, and PHP – Step by Step Guide!


Previously, we learned how to create a simple REST API in PHP. Today, we are going to learn how to create or insert, read, update and delete records with our AJAX CRUD Tutorial. We will use JavaScript, JSON, and PHP.

Overview

What Is AJAX? It stands for "Asynchronous JavaScript and XML".

I’ll try to explain it in the simplest way: Using AJAX will prevent re-loading the whole page for every button click you make. As a result, it makes the user experience better. Your web app will be faster.

Ajax is not a technology, but a group of technologies. This can include HTML, CSS, JavaScript, and server-side scripting like PHP.

I highly recommend studying the previous tutorials first before proceeding here. But if you think you can take this one, then go on.

This tutorial will focus on creating, reading, updating, and deleting database records. We will do it using JavaScript, JSON, and PHP.

jQuery will help us with the AJAX part. JSON data will be handled by the REST API built using PHP.

Program Output - PHP AJAX CRUD Tutorial

Below are the screenshots of our tutorial's final result. You can click an image to view the larger version of it.

Create a record.
Read list of records.
Read one record.
When delete button was clicked.

Let’s proceed to the step-by-step tutorial of our LEVEL 1 source code. Enjoy!

Set Up The REST API

In this tutorial, we are going to use a REST API built with PHP.

We did not include REST API source code because we want you to focus on learning how to code with AJAX, not PHP.

But the good news is, we made a separate tutorial about how to build a simple REST API with PHP. Click here to learn the step-by-step PHP REST API tutorial.

I highly recommend learning our REST API tutorial first. This is because we are going to use that API for the rest of this tutorial.

But if you already have your own REST API that will work with this tutorial, that's okay as well.

In my case, one example where I can access the REST API is: http://localhost/api/product/read.php

That link will show me the list of products from the database, in JSON format. It looks like the following screenshot.

The data above will be consumed by our AJAX app. The list of products will be displayed in the Bootstrap table with buttons like "Read One", "Update" and "Delete". You will see it in the "How To Read JSON Data Using jQuery AJAX?" section of this tutorial.

By the way, I'm using a Chrome extension called JSONView to make the JSON data readable in the browser.

Basic Files & Folders

File Structure

We will have the following files and folders at the end of this LEVEL 1 source code tutorial.

├─ app/
├─── assets/
├────── css/
├───────── style.css
├────── js/
├───────── bootbox.min.js
├───────── jquery.js
├─── products/
├────── create-product.js
├────── delete-product.js
├────── read-one-product.js
├────── read-products.js
├────── update-product.js
├─── app.js
├─ index.html

On the next sections, we will start creating the files and folders to achieve the one above.

Create index.html file

Create index.html file on your project's main folder. Open that file and put 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>Read Products</title>

    <!-- bootstrap CSS -->
	<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

	<!-- custom CSS -->
	<link href="app/assets/css/style.css" rel="stylesheet" />

</head>
<body>

<!-- our app will be injected here -->
<div id="app"></div>

<!-- jQuery library -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
        integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>

<!-- bootstrap JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
        integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous">
    </script>

<!-- bootbox for confirm pop up -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>

<!-- app js script -->
<script src="app/app.js"></script>

<!-- products scripts -->
<script src="app/products/read-products.js"></script>
<script src="app/products/create-product.js"></script>
<script src="app/products/read-one-product.js"></script>
<script src="app/products/update-product.js"></script>
<script src="app/products/delete-product.js"></script>

</body>
</html>

Create custom CSS file

  1. Create "app" folder.
  2. Open the "app" folder and create the "assets" folder.
  3. Open the "assets" folder and create the "css" folder.
  4. Open the "css" folder and create "style.css" file.

The "style.css" file is our custom CSS file. You can put any CSS in this file for additional web page styling. In our case, we have the following CSS code inside the "style.css" file.

.m-r-10px{ margin-right:10px; }
.m-b-10px{ margin-bottom:10px; }
.m-b-15px{ margin-bottom:15px; }
.m-b-20px{ margin-bottom:20px; }
.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%; }
.display-none{ display:none; }
.padding-bottom-2em{ padding-bottom:2em; }
.width-30-pct{ width:30%; }
.width-40-pct{ width:40%; }
.overflow-hidden{ overflow:hidden; }
.margin-right-1em{ margin-right:1em; }
.right-margin{ margin:0 .5em 0 0; }
.margin-bottom-1em { margin-bottom:1em; }
.margin-zero{ margin:0; }
.text-align-center{ text-align:center; }

Use jQuery, Bootstrap, and Bootbox.js libraries

As you can see in the index.html file, we are using jQuery and Bootbox.js libraries.

jQuery JavaScript library is needed to make it easy for us to control interactions like button click and form submission. In this tutorial, we are using jQuery version 3.6.0. jQuery CDN is here.

Bootstrap makes it easy for us to have a good-looking user interface. We are using Bootstrap version 3.3.7 in this tutorial. Bootstrap CDN is here.

Bootbox.js library is needed to make the "delete" confirmation dialog box look better. We are using Bootbox.js version 4.4.0 in this tutorial. Bootbox.js CDN is here.

Create app.js file

The "app.js" file contains some basic HTML and JavaScript functions that can be used by other JS files in our app.

  1. Open "app" folder.
  2. Inside that "app" folder, create "app.js" file.
  3. Open "app.js" file and put the following code.
$(document).ready(function(){

    // app html
    var app_html=`
        <div class='container'>

            <div class='page-header'>
                <h1 id='page-title'>Read Products</h1>
            </div>

            <!-- this is where the contents will be shown. -->
            <div id='page-content'></div>

        </div>`;

    // inject to 'app' in index.html
    $("#app").html(app_html);

});

// change page title
function changePageTitle(page_title){

	// change page title
	$('#page-title').text(page_title);

	// change title tag
	document.title=page_title;
}

// function to make form values to json format
$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

Create "products" scripts

Now, we will create several JavaScript files.

  1. Open "app" folder.
  2. Create "products" folder inside "app" folder.
  3. Create the following files inside "products" folder:
    • read-products.js
    • create-product.js
    • read-one-product.js
    • update-product.js
    • delete-product.js

What's the code inside the JavaScript files above? For now, we will leave them empty. But we will fill them out in the next several sections of this tutorial.

Output

Our code so far will have almost empty output. It should look like the following.

How To Read JSON Data Using jQuery AJAX?

Show products on first page load

  1. Open "app" folder.
  2. Open "products" folder inside the "app" folder.
  3. Open read-products.js file inside the "products" folder.

The following code will call the showProducts() method on first load of the web page.

The showProducts() will show the list of products in an HTML table. Put the following code inside read-products.js file.

$(document).ready(function(){

    // show list of product on first load
    showProducts();

});

// showProducts() method will be here

Show products on click of a button

The following code will call showProducts() method in a click of a button with read-products-button class.

The button can be found in the "create product" and "update product" HTML template. We will see it in the next sections.

Put the following code under the showProducts(); of the previous section.

// when a 'read products' button was clicked
$(document).on('click', '.read-products-button', function(){
	showProducts();
});

Create showProducts() function

Now we will create the showProducts() method. Replace // showProducts() method will be here comment in read-products.js file with the following code.

// function to show list of products
function showProducts(){

}

Get list of products

The following code will contact our API to get the list of products in JSON format. Put the following code after the opening curly brace of the previous section.

// get list of products from the API
$.getJSON("http://localhost/api/product/read.php", function(data){

});

Add "Create Product" button

We have to add a "Create Product" button in the "products list" view. We will make this button work later in this tutorial.

Place the following code after the opening curly brace of the previous section.

// html for listing products
var read_products_html=`
    <!-- when clicked, it will load the create product form -->
    <div id='create-product' class='btn btn-primary pull-right m-b-15px create-product-button'>
        <span class='glyphicon glyphicon-plus'></span> Create Product
    </div>

Build HTML table

We have to start building the HTML table where the list of products will appear.

The following code will build an HTML table with its heading. Place it after the previous section's code.

<!-- start table -->
<table class='table table-bordered table-hover'>

    <!-- creating our table heading -->
    <tr>
        <th class='w-25-pct'>Name</th>
        <th class='w-10-pct'>Price</th>
        <th class='w-15-pct'>Category</th>
        <th class='w-25-pct text-align-center'>Action</th>
    </tr>`;

	// rows will be here

// end table
read_products_html+=`</table>`;

Build table row per record

We will loop through each record returned by the API. In each record, we will create a table row.

Aside from product data, the table row will have the "action" buttons as well. These include the "Read One", "Edit" and "Delete" buttons.

Replace "// rows will be here" comment of the previous section with the following code.

// loop through returned list of data
$.each(data.records, function(key, val) {

    // creating new table row per record
    read_products_html+=`
        <tr>

            <td>` + val.name + `</td>
            <td>$` + val.price + `</td>
            <td>` + val.category_name + `</td>

            <!-- 'action' buttons -->
            <td>
                <!-- read product button -->
                <button class='btn btn-primary m-r-10px read-one-product-button' data-id='` + val.id + `'>
                    <span class='glyphicon glyphicon-eye-open'></span> Read
                </button>

                <!-- edit button -->
                <button class='btn btn-info m-r-10px update-product-button' data-id='` + val.id + `'>
                    <span class='glyphicon glyphicon-edit'></span> Edit
                </button>

                <!-- delete button -->
                <button class='btn btn-danger delete-product-button' data-id='` + val.id + `'>
                    <span class='glyphicon glyphicon-remove'></span> Delete
                </button>
            </td>

        </tr>`;
});

Inject to page content

We have to make the HTML table appear on our webpage. We will do this by injecting the table into the "page-content" div.

Place the following code after the closing "table" tag

// inject to 'page-content' of our app
$("#page-content").html(read_products_html);

5.9 Change page title

The following code will change the "title" seen on the web page and the "title" seen on the browser tab.

Place the following code after the previous section's code.

// chage page title
changePageTitle("Read Products");

Output

After doing all the steps above, the output should look like the following.

How To Create or Insert Data Using jQuery AJAX?

Handle "Create Product" Button Click

  1. Open "app" folder.
  2. Open "products" folder inside the "app" folder.
  3. Open create-product.js file inside the "products" folder.

The following code will handle a click of a button. This button should have "create-product-button" class.

Place the following code inside create-product.js file.

$(document).ready(function(){

    // show html form when 'create product' button was clicked
    $(document).on('click', '.create-product-button', function(){
		// categories api call will be here
    });

	// 'create product form' handle will be here
});

Get list of categories from API

We need to get list of categories from the API because we will build the "categories" select field. This is where the user can select the category of the product.

Replace "// categories api call will be here" of the previous section with the following code.

// load list of categories
$.getJSON("http://localhost/api/category/read.php", function(data){

});

Build "categories option" select field

This is where we build the HTML "select" field with the "categories" option.

Place the following code after the opening curly brace of the previous section.

// build categories option html
// loop through returned list of data
var categories_options_html=`<select name='category_id' class='form-control'>`;
$.each(data.records, function(key, val){
    categories_options_html+=`<option value='` + val.id + `'>` + val.name + `</option>`;
});
categories_options_html+=`</select>`;

Add "Read Products" button

The "read products" button is needed so that we can go back to the products list.

Place the following code after the previous section's code.

// we have our html form here where product information will be entered
// we used the 'required' html5 property to prevent empty fields
var create_product_html=`

    <!-- 'read products' button to show list of products -->
    <div id='read-products' class='btn btn-primary pull-right m-b-15px read-products-button'>
        <span class='glyphicon glyphicon-list'></span> Read Products
    </div>

Build "Create Product" HTML Form

Now we will build the actual "creat product" HTML form. This is where the user can enter the new product information that will be sent to the server.

Place the following code after the previous section's code.

<!-- 'create product' html form -->
<form id='create-product-form' action='#' method='post' border='0'>
    <table class='table table-hover table-responsive table-bordered'>

        <!-- name field -->
        <tr>
            <td>Name</td>
            <td><input type='text' name='name' class='form-control' required /></td>
        </tr>

        <!-- price field -->
        <tr>
            <td>Price</td>
            <td><input type='number' min='1' name='price' class='form-control' required /></td>
        </tr>

        <!-- description field -->
        <tr>
            <td>Description</td>
            <td><textarea name='description' class='form-control' required></textarea></td>
        </tr>

        <!-- categories 'select' field -->
        <tr>
            <td>Category</td>
            <td>` + categories_options_html + `</td>
        </tr>

        <!-- button to submit form -->
        <tr>
            <td></td>
            <td>
                <button type='submit' class='btn btn-primary'>
                    <span class='glyphicon glyphicon-plus'></span> Create Product
                </button>
            </td>
        </tr>

    </table>
</form>`;

Show "Create Product" form and change page title

We have to make the HTML button and form appear on our web page. We will change the page title as well.

Place the following code after the previous section's code.

// inject html to 'page-content' of our app
$("#page-content").html(create_product_html);

// chage page title
changePageTitle("Create Product");

Handle "create product" form submit

If the "create product" form is submitted, we need a script to handle it.

Find "// 'create product form' handle will be here" and replace it with the following code.

// will run if create product form was submitted
$(document).on('submit', '#create-product-form', function(){
	// form data will be here
});

Get form data

This is how we get data entered in our "create product" HTML form.

Replace "// form data will be here" of the previous section with the following code.

// get form data
var form_data=JSON.stringify($(this).serializeObject());

Now we will send the data to the server.

Place the following code after the previous section's code.

// submit form data to api
$.ajax({
	url: "http://localhost/api/product/create.php",
	type : "POST",
	contentType : 'application/json',
	data : form_data,
	success : function(result) {
		// product was created, go back to products list
		showProducts();
	},
	error: function(xhr, resp, text) {
		// show error to console
		console.log(xhr, resp, text);
	}
});

return false;

Output

The output should look like the following.

How To Read One Data Using jQuery AJAX?

Handle "read one" button click

The "read one" button is seen on the "product list" view. When click, it should show the complete product details.

  1. Open "app" folder.
  2. Inside the "app" folder, open "products" folder.
  3. Inside the "products" folder, open "read-one-product.js" file.

Place the following code inside "read-one-product.js" file.

$(document).ready(function(){

    // handle 'read one' button click
    $(document).on('click', '.read-one-product-button', function(){
		// product ID will be here
    });

});

Get product ID

Our script need to identify the record to be read. We do it by getting the product ID.

Replace "// product ID will be here" of the previous section with the following code.

// get product id
var id = $(this).attr('data-id');

Read one record from API

We will send the product ID to the API. It will return the data based on the given ID.

Place the following code after the previous section's code.

// read product record based on given ID
$.getJSON("http://localhost/api/product/read_one.php?id=" + id, function(data){
	// read products button will be here
});

Add "read products" button

We need the "read products" button so we can go back to the products list.

Replace "// read products button will be here" of the previous section with the following code.

// start html
var read_one_product_html=`

    <!-- when clicked, it will show the product's list -->
    <div id='read-products' class='btn btn-primary pull-right m-b-15px read-products-button'>
        <span class='glyphicon glyphicon-list'></span> Read Products
    </div>

Show record data in HTML table

We will place the product information returned by the API to an HTML table.

Place the following code after the previous section's code.

<!-- product data will be shown in this table -->
<table class='table table-bordered table-hover'>

    <!-- product name -->
    <tr>
        <td class='w-30-pct'>Name</td>
        <td class='w-70-pct'>` + data.name + `</td>
    </tr>

    <!-- product price -->
    <tr>
        <td>Price</td>
        <td>` + data.price + `</td>
    </tr>

    <!-- product description -->
    <tr>
        <td>Description</td>
        <td>` + data.description + `</td>
    </tr>

    <!-- product category name -->
    <tr>
        <td>Category</td>
        <td>` + data.category_name + `</td>
    </tr>

</table>`;

Show "Read One Product" HTML table and change page title

We have to make the HTML button and table appear on our web page. We will change the page title as well.

Place the following code after the previous section's code.

// inject html to 'page-content' of our app
$("#page-content").html(read_one_product_html);

// chage page title
changePageTitle("Create Product");

Output

The output should look like the following.

How To Update Data Using jQuery AJAX?

Handle "udpate product" button click

The "edit" button is seen on the "product list" view. When click, it should show the "update product" form filled out with product information.

  1. Open "app" folder.
  2. Inside the "app" folder, open "products" folder.
  3. Inside the "products" folder, open "update-product.js" file.

Place the following code inside "update-product.js" file.

$(document).ready(function(){

    // show html form when 'update product' button was clicked
    $(document).on('click', '.update-product-button', function(){
		// product ID will be here
    });

	// 'update product form' submit handle will be here
});

8.2 Get product ID

Our script need to identify the record to be read. We do it by getting the product ID.

Replace "// product ID will be here" of the previous section with the following code.

// get product id
var id = $(this).attr('data-id');

Read product information

To fill out our "update product" HTML form, we need to get product information from the API.

Place the following code after the previous section's code.

// read one record based on given product id
$.getJSON("http://localhost/api/product/read_one.php?id=" + id, function(data){

	// values will be used to fill out our form
	var name = data.name;
	var price = data.price;
	var description = data.description;
	var category_id = data.category_id;
	var category_name = data.category_name;

	// load list of categories will be here
});

Get list of categories

A list of categories is needed for product category options. Category records will be rendered as options in a "select" HTML input field.

Replace "// load list of categories will be here" of the previous section with the following code.

// load list of categories
$.getJSON("http://localhost/api/category/read.php", function(data){

	// build 'categories option' html
	// loop through returned list of data
        var categories_options_html=`<select name='category_id' class='form-control'>`;

        $.each(data.records, function(key, val){
            // pre-select option is category id is the same
            if(val.id==category_id){ categories_options_html+=`<option value='` + val.id + `' selected>` + val.name + `</option>`; }

            else{ categories_options_html+=`<option value='` + val.id + `'>` + val.name + `</option>`; }
        });
        categories_options_html+=`</select>`;

	// update product html will be here
});

Add "Read Products" button

The "read products" button is needed so that we can go back to the products list.

Replace "// update product html will be here" of the previous section with the following code.

// store 'update product' html to this variable
var update_product_html=`
    <div id='read-products' class='btn btn-primary pull-right m-b-15px read-products-button'>
        <span class='glyphicon glyphicon-list'></span> Read Products
    </div>

Build "Update Product" form

Now we will build the "update product" HTML form. This form will be built with an HTML table and the input fields are filled out with product information.

Place the following code after the previous section's code.

<!-- build 'update product' html form -->
<!-- we used the 'required' html5 property to prevent empty fields -->
<form id='update-product-form' action='#' method='post' border='0'>
    <table class='table table-hover table-responsive table-bordered'>

        <!-- name field -->
        <tr>
            <td>Name</td>
            <td><input value=\"` + name + `\" type='text' name='name' class='form-control' required /></td>
        </tr>

        <!-- price field -->
        <tr>
            <td>Price</td>
            <td><input value=\"` + price + `\" type='number' min='1' name='price' class='form-control' required /></td>
        </tr>

        <!-- description field -->
        <tr>
            <td>Description</td>
            <td><textarea name='description' class='form-control' required>` + description + `</textarea></td>
        </tr>

        <!-- categories 'select' field -->
        <tr>
            <td>Category</td>
            <td>` + categories_options_html + `</td>
        </tr>

        <tr>

            <!-- hidden 'product id' to identify which record to delete -->
            <td><input value=\"` + id + `\" name='id' type='hidden' /></td>

            <!-- button to submit form -->
            <td>
                <button type='submit' class='btn btn-info'>
                    <span class='glyphicon glyphicon-edit'></span> Update Product
                </button>
            </td>

        </tr>

    </table>
</form>`;

Show "Update Product" form and change page title

We need to show our "update product" HTML on our webpage. We will change the page title as well.

Put the following code after the previous section's code.

// inject to 'page-content' of our app
$("#page-content").html(update_product_html);

// chage page title
changePageTitle("Update Product");

Handle "udpate product" form submission

If the "update product" form is submitted, we need a script to handle it.

Find "// 'update product form' submit handle will be here" and replace it with the following code.

// will run if 'create product' form was submitted
$(document).on('submit', '#update-product-form', function(){

	// get form data will be here 

	return false;
});

Get form data

We will get the product information from our "update product" HTML form.

Replace "// get form data will be here" of the previous section with the following code.

// get form data
var form_data=JSON.stringify($(this).serializeObject());

Send form data to server

After getting the form data, we will send the data to our API.

Place the following code after the previous section's code.

// submit form data to api
$.ajax({
	url: "http://localhost/api/product/update.php",
	type : "POST",
	contentType : 'application/json',
	data : form_data,
	success : function(result) {
		// product was created, go back to products list
		showProducts();
	},
	error: function(xhr, resp, text) {
		// show error to console
		console.log(xhr, resp, text);
	}
});

Output

The output should look like the following.

How To Delete Data Using AJAX?

Handle "Delete Product" button click

The "delete product" button is seen in the "read products" view. When it was clicked, we need to handle it.

  1. Open "app" folder.
  2. Inside the "app" folder, open "products" folder.
  3. Inside the "products" folder, open "delete-product.js" file.

Place the following code inside "delete-product.js" file.

$(document).ready(function(){

    // will run if the delete button was clicked
    $(document).on('click', '.delete-product-button', function(){
		// product id will be here
	});
});

Get product ID

The product ID is needed to identify which record to delete using the API.

Replace "// product id will be here" of the previous section with the following code.

// get the product id
var product_id = $(this).attr('data-id');

Show "delete confirmation" dialog box

This is where we will use the Bootbox.js library. We will show a dialog box with "Are you sure?" message with "Yes" and "No" buttons.

Place the following code after the previous section's code.

// bootbox for good looking 'confirm pop up'
bootbox.confirm({

	message: "<h4>Are you sure?</h4>",
	buttons: {
		confirm: {
			label: '<span class="glyphicon glyphicon-ok"></span> Yes',
			className: 'btn-danger'
		},
		cancel: {
			label: '<span class="glyphicon glyphicon-remove"></span> No',
			className: 'btn-primary'
		}
	},
	callback: function (result) {
		// delete request will be here
	}
});

Delete record using API

If the user clicked "Yes" on the dialog box, a "delete" request will be sent to the API.

Replace "// delete request will be here" of the previous section with the following code.

if(result==true){

	// send delete request to api / remote server
	$.ajax({
		url: "http://localhost/api/product/delete.php",
		type : "POST",
		dataType : 'json',
		data : JSON.stringify({ id: product_id }),
		success : function(result) {

			// re-load list of products
			showProducts();
		},
		error: function(xhr, resp, text) {
			console.log(xhr, resp, text);
		}
	});

}

Output

How To Search Data Using jQuery AJAX?

This feature is part of our LEVEL 2 source code.

Include two JS file in index.html

<!-- products scripts -->
<script src="app/products/products.js"></script>
<script src="app/products/search-product.js"></script>

Create products.js file

The "products.js" file will contain any functions that can be used by other product components like our "read-products.js" or "search-products.js" files.

Open "app" folder. Open "products" folder. Create "products.js" file.

Open the "products.js" file and put the following code.

// product list html
function readProductsTemplate(data, keywords){

    var read_products_html=`
		<!-- search products form -->
		<form id='search-product-form' action='#' method='post'>
		<div class='input-group pull-left w-30-pct'>

			<input type='text' value='` + keywords + `' name='keywords' class='form-control product-search-keywords' placeholder='Search products...' />

			<span class='input-group-btn'>
				<button type='submit' class='btn btn-default' type='button'>
					<span class='glyphicon glyphicon-search'></span>
				</button>
			</span>

		</div>
		</form>

		<!-- when clicked, it will load the create product form -->
		<div id='create-product' class='btn btn-primary pull-right m-b-15px create-product-button'>
			<span class='glyphicon glyphicon-plus'></span> Create Product
		</div>

		<!-- start table -->
		<table class='table table-bordered table-hover'>

			<!-- creating our table heading -->
			<tr>
				<th class='w-25-pct'>Name</th>
				<th class='w-10-pct'>Price</th>
				<th class='w-15-pct'>Category</th>
				<th class='w-25-pct text-align-center'>Action</th>
			</tr>`;

    // loop through returned list of data
    $.each(data.records, function(key, val) {

        // creating new table row per record
        read_products_html+=`<tr>

            <td>` + val.name + `</td>
            <td>$` + val.price + `</td>
            <td>` + val.category_name + `</td>

            <!-- 'action' buttons -->
            <td>
                <!-- read product button -->
                <button class='btn btn-primary m-r-10px read-one-product-button' data-id='` + val.id + `'>
                    <span class='glyphicon glyphicon-eye-open'></span> Read
                </button>

                <!-- edit button -->
                <button class='btn btn-info m-r-10px update-product-button' data-id='` + val.id + `'>
                    <span class='glyphicon glyphicon-edit'></span> Edit
                </button>

                <!-- delete button -->
                <button class='btn btn-danger delete-product-button' data-id='` + val.id + `'>
                    <span class='glyphicon glyphicon-remove'></span> Delete
                </button>
            </td>
        </tr>`;
    });

    // end table
    read_products_html+=`</table>`;

    // inject to 'page-content' of our app
    $("#page-content").html(read_products_html);
}

Create search-product.js file

The "search-product.js" file will contain a code that catches the submission of the "search product" form.

Open "app" folder. Open the "products" folder. Create "search-products.js" file.

Open the "search-products.js" file and put the following code.

$(document).ready(function(){

    // when a 'search products' button was clicked
    $(document).on('submit', '#search-product-form', function(){

        // get search keywords
        var keywords = $(this).find(":input[name='keywords']").val();

        // get data from the api based on search keywords
        $.getJSON("http://localhost/api/product/search.php?s=" + keywords, function(data){

            // template in products.js
            readProductsTemplate(data, keywords);

            // chage page title
            changePageTitle("Search products: " + keywords);

        });

        // prevent whole page reload
        return false;
    });

});

Change read-products.js

We want the "product list" and "search product" to have the same HTML table template. To do this, we will use the readProductsTemplate() function of the products.js file.

Open "app" folder. Open "products" folder. Open the "read-products.js' file. Change the showProducts() function to the following code.

// function to show list of products
function showProducts(){

    // get list of products from the API
    $.getJSON("http://localhost/api/product/read.php", function(data){

        // html for listing products
        readProductsTemplate(data, "");

        // chage page title
        changePageTitle("Read Products");

    });
}

Output

How To Paginate Data Using jQuery AJAX?

This feature is part of our LEVEL 2 and LEVEL 3 source codes.

Change JSON URL

To make pagination work, we'll have to change the JSON URL. The contents of this new JSON data will include the "paging" node. It looks like the following.

So we will change the JSON URL from:

http://localhost/api/product/read.php

to

http://localhost/api/product/read_paging.php

It means we have to change something in our code. See the change in the next section.

Show products using JSON URL

Open /app/products/read-products.js file. Replace the code with the following.

$(document).ready(function(){

    // show list of product on first load
    showProductsFirstPage();

    // when a 'read products' button was clicked
    $(document).on('click', '.read-products-button', function(){
        showProductsFirstPage();
    });

    // when a 'page' button was clicked
    $(document).on('click', '.pagination li', function(){
        // get json url
        var json_url=$(this).find('a').attr('data-page');

        // show list of products
        showProducts(json_url);
    });

});

function showProductsFirstPage(){
    var json_url="http://localhost/api/product/read_paging.php";
    showProducts(json_url);
}

// function to show list of products
function showProducts(json_url){

    // get list of products from the API
    $.getJSON(json_url, function(data){

        // html for listing products
        readProductsTemplate(data, "");

        // chage page title
        changePageTitle("Read Products");

    });
}

Add Pagination HTML

Open /app/products/products.js file. Find the ending "table" tag and put the following code under it.

// pagination
if(data.paging){
    read_products_html+="<ul class='pagination pull-left margin-zero padding-bottom-2em'>";

        // first page
        if(data.paging.first!=""){
            read_products_html+="<li><a data-page='" + data.paging.first + "'>First Page</a></li>";
        }

        // loop through pages
        $.each(data.paging.pages, function(key, val){
            var active_page=val.current_page=="yes" ? "class='active'" : "";
            read_products_html+="<li " + active_page + "><a data-page='" + val.url + "'>" + val.page + "</a></li>";
        });

        // last page
        if(data.paging.last!=""){
            read_products_html+="<li><a data-page='" + data.paging.last + "'>Last Page</a></li>";
        }
    read_products_html+="</ul>";
}

Output

After making the changes above, run index.html again. Do a hard refresh. You should see the paging buttons like the one below.

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. Set up the "api" by following the README.txt inside the "api" folder.
  3. Open your browser and run index.html
  4. If you can see the list of "product" records, it means your set up is correct.

Download LEVEL 1 Source Code

FEATURES LEVEL 1
Create product YES
Read product YES
Read one product YES
Update product YES
Delete product YES
Bootstrap UI YES
PHP REST API source code YES
FREE email support for 3 months YES
Source code updates via email YES
$20 - Download now

Download LEVEL 2 Source Code

FEATURES LEVEL 2
All features of LEVEL 1 YES
Search products YES
Pagination of products & search products YES
Create category YES
Read category YES
Read one category YES
Update category YES
Delete category YES
Search categories YES
Pagination of categories & search categories YES
Navigation bar YES
FREE email support for 6 months YES
$40 - Download now

Download LEVEL 3 Source Code

FEATURES LEVEL 3
All features of LEVEL 2 YES
Inline editing of products & categories YES
Export CSV of products & categories YES
Bootstrap tooltip on some products & categories buttons YES
FREE email support for 1 year YES
$50 - Download now

Why download?

Do you need more reasons to download it?

MORE REASONS TO DOWNLOAD THE CODE ALL
Use new skills for your multiple projects YES
Save huge amount of time learning jQuery AJAX YES
Code examples are direct to the point YES
Well explained and commented source code YES
Fast and friendly email support YES
Free source code updates YES

What's Next?

Our next topic is a bit different: How To Display Facebook Page Events on Website using PHP?

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 our AJAX CRUD Tutorial Using jQuery, JSON and PHP!

PHP OOP CRUD Tutorial – Step By Step Guide!


Previously, we learned how to create or insert, read, update, and delete database records with our PHP and MySQL CRUD tutorial for beginners. This time, we will learn object-oriented programming with PHP & MySQL.

Overview

Our tutorial for today is about creating a simple database application. We can achieve it with the help of this PHP OOP CRUD tutorial. You can use this knowledge in your current or future projects.

We use Bootstrap so that our application will have a decent UI. If you're not yet familiar with what Bootstrap is, and you want to learn how to use it in few steps, I highly recommend following our Bootstrap tutorial first.

There are so many PHP object-oriented programming tutorials on the web today, they have different examples and implementations. Some might be completely correct, some maybe not.

I'm writing this tutorial with a clear goal: to give the best PHP OOP CRUD tutorial for beginners. I welcome your comments and suggestions to help me achieve this.

We want to learn the correct PHP OOP implementation. There are PHP frameworks such as CakePHP, CodeIgniter, and Laravel that correctly do it.

Those things are one step higher. For now, we will learn object-oriented programming with PHP & MySQL. Working with a PHP framework should be easy after following this tutorial.

Database Table Structure

The files products.sql and categories.sql are also included in the code download, located at the README folder.

Create a database

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

Create products table

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

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

  • Click php_oop_crud_level_1 database.
  • Click "SQL" tab.
  • Copy the SQL statement below and paste it in the text area.
  • Click the "Go" button.
-- Table structure for table `products`
CREATE TABLE IF NOT EXISTS `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `description` text NOT NULL,
  `price` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  `created` datetime NOT NULL,
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=38 ;

Insert products sample data

We have to put some database records.

Run the following SQL statement using your PhpMyAdmin.

-- Dumping data for table `products`
INSERT INTO `products` (`id`, `name`, `description`, `price`, `category_id`, `created`, `modified`) VALUES
(1, 'LG P880 4X HD', 'My first awesome phone!', 336, 3, '2014-06-01 01:12:26', '2014-05-31 17:12:26'),
(2, 'Google Nexus 4', 'The most awesome phone of 2013!', 299, 2, '2014-06-01 01:12:26', '2014-05-31 17:12:26'),
(3, 'Samsung Galaxy S4', 'How about no?', 600, 3, '2014-06-01 01:12:26', '2014-05-31 17:12:26'),
(6, 'Bench Shirt', 'The best shirt!', 29, 1, '2014-06-01 01:12:26', '2014-05-31 02:12:21'),
(7, 'Lenovo Laptop', 'My business partner.', 399, 2, '2014-06-01 01:13:45', '2014-05-31 02:13:39'),
(8, 'Samsung Galaxy Tab 10.1', 'Good tablet.', 259, 2, '2014-06-01 01:14:13', '2014-05-31 02:14:08'),
(9, 'Spalding Watch', 'My sports watch.', 199, 1, '2014-06-01 01:18:36', '2014-05-31 02:18:31'),
(10, 'Sony Smart Watch', 'The coolest smart watch!', 300, 2, '2014-06-06 17:10:01', '2014-06-05 18:09:51'),
(11, 'Huawei Y300', 'For testing purposes.', 100, 2, '2014-06-06 17:11:04', '2014-06-05 18:10:54'),
(12, 'Abercrombie Lake Arnold Shirt', 'Perfect as gift!', 60, 1, '2014-06-06 17:12:21', '2014-06-05 18:12:11'),
(13, 'Abercrombie Allen Brook Shirt', 'Cool red shirt!', 70, 1, '2014-06-06 17:12:59', '2014-06-05 18:12:49'),
(25, 'Abercrombie Allen Anew Shirt', 'Awesome new shirt!', 999, 1, '2014-11-22 18:42:13', '2014-11-21 19:42:13'),
(26, 'Another product', 'Awesome product!', 555, 2, '2014-11-22 19:07:34', '2014-11-21 20:07:34'),
(27, 'Bag', 'Awesome bag for you!', 999, 1, '2014-12-04 21:11:36', '2014-12-03 22:11:36'),
(28, 'Wallet', 'You can absolutely use this one!', 799, 1, '2014-12-04 21:12:03', '2014-12-03 22:12:03'),
(30, 'Wal-mart Shirt', '', 555, 2, '2014-12-13 00:52:29', '2014-12-12 01:52:29'),
(31, 'Amanda Waller Shirt', 'New awesome shirt!', 333, 1, '2014-12-13 00:52:54', '2014-12-12 01:52:54'),
(32, 'Washing Machine Model PTRR', 'Some new product.', 999, 1, '2015-01-08 22:44:15', '2015-01-07 23:44:15');

Create categories table

Categories table are used to store product categories.

Run the following SQL statement using your PhpMyAdmin.

-- Table structure for table `categories`
CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(256) NOT NULL,
  `created` datetime NOT NULL,
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

Insert categories sample data

We are going to have "Fashion", "Electronics" and "Motors" as categories in our project. I got those three category ideas from eBay, haha!

Run the following SQL statement using your PhpMyAdmin.

-- Dumping data for table `categories`
INSERT INTO `categories` (`id`, `name`, `created`, `modified`) VALUES
(1, 'Fashion', '2014-06-01 00:35:07', '2014-05-30 17:34:33'),
(2, 'Electronics', '2014-06-01 00:35:07', '2014-05-30 17:34:33'),
(3, 'Motors', '2014-06-01 00:35:07', '2014-05-30 17:34:54');

Output

In this section, we were able to set up our database using PhpMyAdmin. It should look like the image below.

We don't have a PHP program output yet. Let's continue on the next section to achieve more output.

Create the Layout Files

To reduce some code mess, we will create the layout files with the codes and assets it needs.

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

Bootstrap CSS asset will be included inside the head tags.

  • Create php-oop-crud-level-1 folder and open it.
  • Create layout_header.php file.
  • Place 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 $page_title; ?></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>
 
    <!-- container -->
    <div class="container">
 
        <?php
        // show page header
        echo "<div class='page-header'>
                <h1>{$page_title}</h1>
            </div>";
        ?>

Create footer layout file

This layout_footer.php will be included at the end of each PHP files that 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-oop-crud-level-1 folder.
  • Create layout_footer.php file.
  • Place the following code.
    </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>
  
<!-- bootbox library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>
 
</body>
</html>

Create custom CSS file

This file is used to change any style we want on our web page. It is also used to override the default style given by Bootstrap.

  • Open php-oop-crud-level-1 folder.
  • Create libs folder.
  • Create css folder.
  • Create custom.css file.
  • Place the following code.
.left-margin{
    margin:0 .5em 0 0;
}
 
.right-button-margin{
    margin: 0 0 1em 0;
    overflow: hidden;
}
 
/* some changes in bootstrap modal */
.modal-body {
    padding: 20px 20px 0px 20px !important;
    text-align: center !important;
}
 
.modal-footer{
    text-align: center !important;
}

Output

The layout files we created in this section is meant to be used inside another PHP file. If we try to run the layout files alone, we won't get any meaningful output.

If you run layout_header.php, it will look like this on the browser.

The custom.css file will look like this.

The layout_footer.php is blank. Let's continue on the next section to see a more meaningful output.

Creating record in PHP the OOP Way

Create a file: create_product.php

Go back to php-oop-crud-level-1 folder, create a file with a name create_product.php and put the following code inside it.

<?php
// set page headers
$page_title = "Create Product";
include_once "layout_header.php";
 
// contents will be here
 
// footer
include_once "layout_footer.php";
?>

Create a "Read Products" Button

The following code will render a button. Replace the comments // contents will be here of the previous section with the following.

echo "<div class='right-button-margin'>
        <a href='index.php' class='btn btn-default pull-right'>Read Products</a>
    </div>";
 
?>
<!-- 'create product' html form will be here -->
<?php

Get a Database Connection

We can use it for retrieving categories or saving new product record later. Put the following code before // set page headers comment of create_product.php file.

// include database and object files
include_once 'config/database.php';
include_once 'objects/product.php';
include_once 'objects/category.php';
 
// get database connection
$database = new Database();
$db = $database->getConnection();
 
// pass connection to objects
$product = new Product($db);
$category = new Category($db);

Create the Database Configuration Class

Getting a database connection will not work without this class. This class file will be included in most PHP files of our PHP OOP CRUD Tutorial.

Create a config folder and inside that folder, create a database.php file. Open that file and put the following code.

<?php
class Database{
  
    // specify your own database credentials
    private $host = "localhost";
    private $db_name = "php_oop_crud_level_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;
    }
}
?>

Create a Form in create_product.php

The following code will render an HTML form. Open create_product.php file.

Replace <!-- 'create product' html form will be here --> comment with the following code.

<!-- PHP post code will be here -->
 
<!-- HTML form for creating a product -->
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post">
 
    <table class='table table-hover table-responsive table-bordered'>
 
        <tr>
            <td>Name</td>
            <td><input type='text' name='name' class='form-control' /></td>
        </tr>
 
        <tr>
            <td>Price</td>
            <td><input type='text' name='price' class='form-control' /></td>
        </tr>
 
        <tr>
            <td>Description</td>
            <td><textarea name='description' class='form-control'></textarea></td>
        </tr>
 
        <tr>
            <td>Category</td>
            <td>
            <!-- categories from database will be here -->
            </td>
        </tr>
 
        <tr>
            <td></td>
            <td>
                <button type="submit" class="btn btn-primary">Create</button>
            </td>
        </tr>
 
    </table>
</form>

Loop Through the Categories Records to show as Drop-down

The following code will retrieve categories and put it in a "select" drop-down.

Replace <!-- categories from database will be here --> comment of the previous section with the following code.

<?php
// read the product categories from the database
$stmt = $category->read();
 
// put them in a select drop-down
echo "<select class='form-control' name='category_id'>";
    echo "<option>Select category...</option>";
 
    while ($row_category = $stmt->fetch(PDO::FETCH_ASSOC)){
        extract($row_category);
        echo "<option value='{$id}'>{$name}</option>";
    }
 
echo "</select>";
?>

Create the Object Class for Categories

Of course, the previous section won't work without the category object class. Create objects folder. Create category.php file. Place the following code.

<?php
class Category{
 
    // database connection and table name
    private $conn;
    private $table_name = "categories";
 
    // object properties
    public $id;
    public $name;
 
    public function __construct($db){
        $this->conn = $db;
    }
 
    // used by select drop-down list
    function read(){
        //select all data
        $query = "SELECT
                    id, name
                FROM
                    " . $this->table_name . "
                ORDER BY
                    name";  
 
        $stmt = $this->conn->prepare( $query );
        $stmt->execute();
 
        return $stmt;
    }
 
}
?>

Prepare readName() method

It will get the category name instead of showing just an ID. Add the following code inside our category.php, you will see this method used in the next few sections.

// used to read category name by its ID
function readName(){
     
    $query = "SELECT name FROM " . $this->table_name . " WHERE id = ? limit 0,1";
 
    $stmt = $this->conn->prepare( $query );
    $stmt->bindParam(1, $this->id);
    $stmt->execute();
 
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
     
    $this->name = $row['name'];
}

Code when the Form was Submitted

The user will enter the values in the HTML form and when the create (submit) button was clicked, values will be sent via POST request, the code below will save it in the database.

Open create_product.php file. Replace <!-- PHP post code will be here --> comment with the following code.

<?php 
// if the form was submitted - PHP OOP CRUD Tutorial
if($_POST){
 
    // set product property values
    $product->name = $_POST['name'];
    $product->price = $_POST['price'];
    $product->description = $_POST['description'];
    $product->category_id = $_POST['category_id'];
 
    // create the product
    if($product->create()){
        echo "<div class='alert alert-success'>Product was created.</div>";
    }
 
    // if unable to create the product, tell the user
    else{
        echo "<div class='alert alert-danger'>Unable to create product.</div>";
    }
}
?>

Create the Object Class for Products

The previous section will not work without the product object. Open objects folder. Create product.php file. Open that file and put the following code.

<?php
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 $timestamp;
 
    public function __construct($db){
        $this->conn = $db;
    }
 
    // create product
    function create(){
 
        //write query
        $query = "INSERT INTO
                    " . $this->table_name . "
                SET
                    name=:name, price=:price, description=:description, category_id=:category_id, created=:created";
 
        $stmt = $this->conn->prepare($query);
 
        // posted values
        $this->name=htmlspecialchars(strip_tags($this->name));
        $this->price=htmlspecialchars(strip_tags($this->price));
        $this->description=htmlspecialchars(strip_tags($this->description));
        $this->category_id=htmlspecialchars(strip_tags($this->category_id));
 
        // to get time-stamp for 'created' field
        $this->timestamp = date('Y-m-d H:i:s');
 
        // bind values 
        $stmt->bindParam(":name", $this->name);
        $stmt->bindParam(":price", $this->price);
        $stmt->bindParam(":description", $this->description);
        $stmt->bindParam(":category_id", $this->category_id);
        $stmt->bindParam(":created", $this->timestamp);
 
        if($stmt->execute()){
            return true;
        }else{
            return false;
        }
 
    }
}
?>

Output

Form to create product.

Categories drop down in the form.

When you fill out the form and clicked the "Create" button.

Changes in the database.

Reading and Paging Record in PHP the OOP Way

In this part of our PHP OOP CRUD tutorial, we will list the records from the database.

Create File: index.php

Create a new file and name it index.php. This file will show the main page of our web app. Put the following code inside it.

<?php
// set page header
$page_title = "Read Products";
include_once "layout_header.php";
 
// contents will be here
 
// set page footer
include_once "layout_footer.php";
?>

Add a "Create Product" button

The following code will render a button. When this button was clicked, it will show us a page where we can create a record. Replace the // contents will be here comments in the previous section with the following code.

echo "<div class='right-button-margin'>
    <a href='create_product.php' class='btn btn-default pull-right'>Create Product</a>
</div>";

Configure Pagination Variables

Pagination is very important if you have thousands of data from the database. Put the following code before the set page header comment of index.php file.

// page given in URL parameter, default page is one
$page = isset($_GET['page']) ? $_GET['page'] : 1;
 
// set number of records per page
$records_per_page = 5;
 
// calculate for the query LIMIT clause
$from_record_num = ($records_per_page * $page) - $records_per_page;
 
// retrieve records here

Retrieve Records from the Database

Now we will retrieve data from the database. Replace // retrieve records here comment of index.php with the following code.

// include database and object files
include_once 'config/database.php';
include_once 'objects/product.php';
include_once 'objects/category.php';
 
// instantiate database and objects
$database = new Database();
$db = $database->getConnection();
 
$product = new Product($db);
$category = new Category($db);
 
// query products
$stmt = $product->readAll($from_record_num, $records_per_page);
$num = $stmt->rowCount();

Add readAll() Method in product.php

Retrieving records in the previous section won't work without this method. Put the following code inside our "product.php" file which is inside the "objects" folder.

function readAll($from_record_num, $records_per_page){
 
    $query = "SELECT
                id, name, description, price, category_id
            FROM
                " . $this->table_name . "
            ORDER BY
                name ASC
            LIMIT
                {$from_record_num}, {$records_per_page}";
 
    $stmt = $this->conn->prepare( $query );
    $stmt->execute();
 
    return $stmt;
}

Display data from the database

This time, we will show the list of records to the user. An HTML table will hold our data. Put the following code after the section 6.2 code.

// display the products if there are any
if($num>0){
 
    echo "<table class='table table-hover table-responsive table-bordered'>";
        echo "<tr>";
            echo "<th>Product</th>";
            echo "<th>Price</th>";
            echo "<th>Description</th>";
            echo "<th>Category</th>";
            echo "<th>Actions</th>";
        echo "</tr>";
 
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
 
            extract($row);
 
            echo "<tr>";
                echo "<td>{$name}</td>";
                echo "<td>{$price}</td>";
                echo "<td>{$description}</td>";
                echo "<td>";
                    $category->id = $category_id;
                    $category->readName();
                    echo $category->name;
                echo "</td>";
 
                echo "<td>";
                    // read one, edit and delete button will be here
                echo "</td>";
 
            echo "</tr>";
 
        }
 
    echo "</table>";
 
    // paging buttons will be here
}
 
// tell the user there are no products
else{
    echo "<div class='alert alert-info'>No products found.</div>";
}

Put the Read, Edit and Delete Action Buttons

The following code will render three buttons: Read, Edit and Delete button.

Inside the "while" loop of the previous section, there is a comment "read one, edit and delete button will be here", replace that with the following code.

// read, edit and delete buttons
echo "<a href='read_one.php?id={$id}' class='btn btn-primary left-margin'>
    <span class='glyphicon glyphicon-list'></span> Read
</a>
 
<a href='update_product.php?id={$id}' class='btn btn-info left-margin'>
    <span class='glyphicon glyphicon-edit'></span> Edit
</a>
 
<a delete-id='{$id}' class='btn btn-danger delete-object'>
    <span class='glyphicon glyphicon-remove'></span> Delete
</a>";

Create paging.php for Paging Buttons

The following code will show our pagination buttons. Create a new file and name it "paging.php". Open that file and put the following code.

<?php
echo "<ul class='pagination'>";
 
// button for first page
if($page>1){
    echo "<li><a href='{$page_url}' title='Go to the first page.'>";
        echo "First";
    echo "</a></li>";
}
 
// calculate total pages
$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><a href='" .$page_url. "page={$total_pages}' title='Last page is {$total_pages}.'>";
        echo "Last";
    echo "</a></li>";
}
 
echo "</ul>";
?>

Add the countAll() method in objects/product.php

The following code will be used to count the total number of records in the database. This will be used for pagination.

Open your product.php file which is inside the "objects" folder. Add the following method in the class.

// used for paging products
public function countAll(){
 
    $query = "SELECT id FROM " . $this->table_name . "";
 
    $stmt = $this->conn->prepare( $query );
    $stmt->execute();
 
    $num = $stmt->rowCount();
 
    return $num;
}

Include paging.php in index.php

The following code will show our pagination buttons under our records list. Put the following code after the closing "table" tag of section 6.6 above.

// the page where this paging is used
$page_url = "index.php?";
 
// count all products in the database to calculate total pages
$total_rows = $product->countAll();
 
// paging buttons here
include_once 'paging.php';

Output

Run http://localhost/php-oop-crud-level-1/index.php on your browser, you should see something like the image below.

List of records, page 1.

List of records, page 2.

Updating Record in PHP the OOP Way

I know our PHP OOP CRUD tutorial is kinda long. Please take a break or drink some coffee first!

Create File: update_product.php

Create update_product.php file, open that file and put the following code.

<?php
// retrieve one product will be here
 
// set page header
$page_title = "Update Product";
include_once "layout_header.php";
 
// contents will be here
 
// set page footer
include_once "layout_footer.php";
?>

Create a "Read Products" Button

The following code will render a button. This button, when clicked, will let us go back to the records list. Replace the previous section's "contents will be here" comments with the following code.

echo "<div class='right-button-margin'>
          <a href='index.php' class='btn btn-default pull-right'>Read Products</a>
     </div>";
 
?>
<!-- 'update product' form will be here -->

Retrieve One Product Information Based on the Given ID.

The following code will retrieve data that will populate our HTML form. This is important because this will let the user know what exactly the record he is updating.

Open update_product.php file. Replace "// retrieve one product will be here" comment with the following code.

// get ID of the product to be edited
$id = isset($_GET['id']) ? $_GET['id'] : die('ERROR: missing ID.');
 
// include database and object files
include_once 'config/database.php';
include_once 'objects/product.php';
include_once 'objects/category.php';
 
// get database connection
$database = new Database();
$db = $database->getConnection();
 
// prepare objects
$product = new Product($db);
$category = new Category($db);
 
// set ID property of product to be edited
$product->id = $id;
 
// read the details of product to be edited
$product->readOne();

Add readOne() method in the Product Object Class.

The readOne() method used in the previous section will not work without the following code inside /objects/product.php file.

function readOne(){
 
    $query = "SELECT
                name, price, description, category_id
            FROM
                " . $this->table_name . "
            WHERE
                id = ?
            LIMIT
                0,1";
 
    $stmt = $this->conn->prepare( $query );
    $stmt->bindParam(1, $this->id);
    $stmt->execute();
 
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
 
    $this->name = $row['name'];
    $this->price = $row['price'];
    $this->description = $row['description'];
    $this->category_id = $row['category_id'];
}

Put the Values in the Form.

Now we can put the latest values to each form elements. Replace "<!-- 'update product' form will be here -->" comment of update_product.php with the following code.

<!-- post code will be here -->
 
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"] . "?id={$id}");?>" method="post">
    <table class='table table-hover table-responsive table-bordered'>
 
        <tr>
            <td>Name</td>
            <td><input type='text' name='name' value='<?php echo $product->name; ?>' class='form-control' /></td>
        </tr>
 
        <tr>
            <td>Price</td>
            <td><input type='text' name='price' value='<?php echo $product->price; ?>' class='form-control' /></td>
        </tr>
 
        <tr>
            <td>Description</td>
            <td><textarea name='description' class='form-control'><?php echo $product->description; ?></textarea></td>
        </tr>
 
        <tr>
            <td>Category</td>
            <td>
                <!-- categories select drop-down will be here -->
            </td>
        </tr>
 
        <tr>
            <td></td>
            <td>
                <button type="submit" class="btn btn-primary">Update</button>
            </td>
        </tr>
 
    </table>
</form>

Loop Through the Categories Records to show as Drop-down

The following code will list the categories in a drop-down.

Notice that we put "if($product->category_id==$category_id){..." inside the while loop. This is to pre-select the option of the current record.

Replace the previous section's comments "categories select drop-down will be here" with the following code.

<?php
$stmt = $category->read();
 
// put them in a select drop-down
echo "<select class='form-control' name='category_id'>";
 
    echo "<option>Please select...</option>";
    while ($row_category = $stmt->fetch(PDO::FETCH_ASSOC)){
        $category_id=$row_category['id'];
        $category_name = $row_category['name'];
 
        // current category of the product must be selected
        if($product->category_id==$category_id){
            echo "<option value='$category_id' selected>";
        }else{
            echo "<option value='$category_id'>";
        }
 
        echo "$category_name</option>";
    }
echo "</select>";
?>

Code When Form was Submitted

The following code will assign the "posted" values to the object properties. Once assigned, it will update the database with those values using the update() method.

Open update_product.php file. Replace "<!-- post code will be here -->" comment with the following code.

<?php 
// if the form was submitted
if($_POST){
 
    // set product property values
    $product->name = $_POST['name'];
    $product->price = $_POST['price'];
    $product->description = $_POST['description'];
    $product->category_id = $_POST['category_id'];
 
    // update the product
    if($product->update()){
        echo "<div class='alert alert-success alert-dismissable'>";
            echo "Product was updated.";
        echo "</div>";
    }
 
    // if unable to update the product, tell the user
    else{
        echo "<div class='alert alert-danger alert-dismissable'>";
            echo "Unable to update product.";
        echo "</div>";
    }
}
?>

Update Code in the Product Class

The following code will make the previous section's "$product->update()" method work. Open our "product.php" which is inside the "objects" folder and add the following code.

function update(){
 
    $query = "UPDATE
                " . $this->table_name . "
            SET
                name = :name,
                price = :price,
                description = :description,
                category_id  = :category_id
            WHERE
                id = :id";
 
    $stmt = $this->conn->prepare($query);
 
    // posted values
    $this->name=htmlspecialchars(strip_tags($this->name));
    $this->price=htmlspecialchars(strip_tags($this->price));
    $this->description=htmlspecialchars(strip_tags($this->description));
    $this->category_id=htmlspecialchars(strip_tags($this->category_id));
    $this->id=htmlspecialchars(strip_tags($this->id));
 
    // bind parameters
    $stmt->bindParam(':name', $this->name);
    $stmt->bindParam(':price', $this->price);
    $stmt->bindParam(':description', $this->description);
    $stmt->bindParam(':category_id', $this->category_id);
    $stmt->bindParam(':id', $this->id);
 
    // execute the query
    if($stmt->execute()){
        return true;
    }
 
    return false;
     
}

Output

Click any "Edit" button in the index page. The update record form should look like the following.

When you submit the form, a message will be shown.

A record was changed in the database.

Read One Record in PHP the OOP Way

We previously made the code for "update record", this section for reading one record from a database will be easier to do.

Create read_one.php file

This is the page where the data of a single record will be displayed. Create a new file and name it "read_one.php", open that file and put the following code.

<?php
// set page headers
$page_title = "Read One Product";
include_once "layout_header.php";
 
// read products button
echo "<div class='right-button-margin'>";
    echo "<a href='index.php' class='btn btn-primary pull-right'>";
        echo "<span class='glyphicon glyphicon-list'></span> Read Products";
    echo "</a>";
echo "</div>";
 
// set footer
include_once "layout_footer.php";
?>

Read one record based on given record ID

The following code will read a single record from the database. Put the following code before the "set page headers" comments of the previous section.

// get ID of the product to be read
$id = isset($_GET['id']) ? $_GET['id'] : die('ERROR: missing ID.');
 
// include database and object files
include_once 'config/database.php';
include_once 'objects/product.php';
include_once 'objects/category.php';
 
// get database connection
$database = new Database();
$db = $database->getConnection();
 
// prepare objects
$product = new Product($db);
$category = new Category($db);
 
// set ID property of product to be read
$product->id = $id;
 
// read the details of product to be read
$product->readOne();

Display record on HTML table

This time, we will display the record details on an HTML table. Put the following code under the closing "div" tag of "Read Products" button.

// HTML table for displaying a product details
echo "<table class='table table-hover table-responsive table-bordered'>";
 
    echo "<tr>";
        echo "<td>Name</td>";
        echo "<td>{$product->name}</td>";
    echo "</tr>";
 
    echo "<tr>";
        echo "<td>Price</td>";
        echo "<td>${$product->price}</td>";
    echo "</tr>";
 
    echo "<tr>";
        echo "<td>Description</td>";
        echo "<td>{$product->description}</td>";
    echo "</tr>";
 
    echo "<tr>";
        echo "<td>Category</td>";
        echo "<td>";
            // display category name
            $category->id=$product->category_id;
            $category->readName();
            echo $category->name;
        echo "</td>";
    echo "</tr>";
 
echo "</table>";

Output

Click any "Read" button in the index page, you should see something like the image below.

Deleting Record in PHP the OOP Way

This is the last coding part of our PHP OOP CRUD Tutorial. Enjoy every code!

Put this JavaScript code in layout_footer.php

Put the following JavaScript code before the closing "body" tag in layout_footer.php file. We used Bootbox.js to make a Bootstrap-style confirm dialog box.

<script>
// JavaScript for deleting product
$(document).on('click', '.delete-object', function(){
 
    var id = $(this).attr('delete-id');
 
    bootbox.confirm({
        message: "<h4>Are you sure?</h4>",
        buttons: {
            confirm: {
                label: '<span class="glyphicon glyphicon-ok"></span> Yes',
                className: 'btn-danger'
            },
            cancel: {
                label: '<span class="glyphicon glyphicon-remove"></span> No',
                className: 'btn-primary'
            }
        },
        callback: function (result) {
 
            if(result==true){
                $.post('delete_product.php', {
                    object_id: id
                }, function(data){
                    location.reload();
                }).fail(function() {
                    alert('Unable to delete.');
                });
            }
        }
    });
 
    return false;
});
</script>

Create delete_product.php

Create a new file and name it "delete_product.php". This file accepts the ID posted by the JavaScript code in the previous section. A record will be deleted from the database based on posted ID.

Open delete_product.php and put the following code.

<?php
// check if value was posted
if($_POST){
 
    // include database and object file
    include_once 'config/database.php';
    include_once 'objects/product.php';
 
    // get database connection
    $database = new Database();
    $db = $database->getConnection();
 
    // prepare product object
    $product = new Product($db);
     
    // set product id to be deleted
    $product->id = $_POST['object_id'];
     
    // delete the product
    if($product->delete()){
        echo "Object was deleted.";
    }
     
    // if unable to delete the product
    else{
        echo "Unable to delete object.";
    }
}
?>

Delete Code in Product Class

The previous section will not work with the "delete()" method in the product object. Open "product.php" which is inside the "objects" folder and put the following code.

// delete the product
function delete(){
 
    $query = "DELETE FROM " . $this->table_name . " WHERE id = ?";
     
    $stmt = $this->conn->prepare($query);
    $stmt->bindParam(1, $this->id);
 
    if($result = $stmt->execute()){
        return true;
    }else{
        return false;
    }
}

Output

Click any "Delete" button in the index page. A pop up confirmation will be shown.

If the user clicks "OK" the record will be deleted and gone in the table.

A record was deleted in the database.

Search Records in PHP the OOP Way

We'll continue by adding the search feature. This will answer the question: How to search data from database in php? This is a very useful feature because you enable your users to easily search a certain data from our MySQL database.

Please note that this is a bonus section. The code in this section is not included in our LEVEL 1 source code download.

Change index.php

We have to change index.php because we are adding a “search” feature and we want our code to be short. Our index.php will now look like the following code.

<?php
// core.php holds pagination variables
include_once 'config/core.php';
 
// include database and object files
include_once 'config/database.php';
include_once 'objects/product.php';
include_once 'objects/category.php';
 
// instantiate database and product object
$database = new Database();
$db = $database->getConnection();
 
$product = new Product($db);
$category = new Category($db);
 
$page_title = "Read Products";
include_once "layout_header.php";
 
// query products
$stmt = $product->readAll($from_record_num, $records_per_page);
 
// specify the page where paging is used
$page_url = "index.php?";
 
// count total rows - used for pagination
$total_rows=$product->countAll();
 
// read_template.php controls how the product list will be rendered
include_once "read_template.php";
 
// layout_footer.php holds our javascript and closing html tags
include_once "layout_footer.php";
?>

Create read_template.php

Why do we need this template? We need it because exactly the same code can be used by index.php and search.php for displaying a list of records. Using a template means lesser code.

This template holds our search form as well.

<?php
// search form
echo "<form role='search' action='search.php'>";
    echo "<div class='input-group col-md-3 pull-left margin-right-1em'>";
        $search_value=isset($search_term) ? "value='{$search_term}'" : "";
        echo "<input type='text' class='form-control' placeholder='Type product name or description...' name='s' id='srch-term' required {$search_value} />";
        echo "<div class='input-group-btn'>";
            echo "<button class='btn btn-primary' type='submit'><i class='glyphicon glyphicon-search'></i></button>";
        echo "</div>";
    echo "</div>";
echo "</form>";
 
// create product button
echo "<div class='right-button-margin'>";
    echo "<a href='create_product.php' class='btn btn-primary pull-right'>";
        echo "<span class='glyphicon glyphicon-plus'></span> Create Product";
    echo "</a>";
echo "</div>";
 
// display the products if there are any
if($total_rows>0){
 
    echo "<table class='table table-hover table-responsive table-bordered'>";
        echo "<tr>";
            echo "<th>Product</th>";
            echo "<th>Price</th>";
            echo "<th>Description</th>";
            echo "<th>Category</th>";
            echo "<th>Actions</th>";
        echo "</tr>";
 
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
 
            extract($row);
 
            echo "<tr>";
                echo "<td>{$name}</td>";
                echo "<td>{$price}</td>";
                echo "<td>{$description}</td>";
                echo "<td>";
                    $category->id = $category_id;
                    $category->readName();
                    echo $category->name;
                echo "</td>";
 
                echo "<td>";
 
                    // read product button
                    echo "<a href='read_one.php?id={$id}' class='btn btn-primary left-margin'>";
                        echo "<span class='glyphicon glyphicon-list'></span> Read";
                    echo "</a>";
 
                    // edit product button
                    echo "<a href='update_product.php?id={$id}' class='btn btn-info left-margin'>";
                        echo "<span class='glyphicon glyphicon-edit'></span> Edit";
                    echo "</a>";
 
                    // delete product button
                    echo "<a delete-id='{$id}' class='btn btn-danger delete-object'>";
                        echo "<span class='glyphicon glyphicon-remove'></span> Delete";
                    echo "</a>";
 
                echo "</td>";
 
            echo "</tr>";
 
        }
 
    echo "</table>";
 
    // paging buttons
    include_once 'paging.php';
}
 
// tell the user there are no products
else{
    echo "<div class='alert alert-danger'>No products found.</div>";
}
?>

Create core.php in "config" folder

Create a new folder and name it "config". Inside that folder, create a new file and name it "core.php".

This file will hold our pagination variables. Using a core.php file is a good practice, it can be used to hold other configuration values that you might need in the future.

Open core.php and put the following code.

<?php
// page given in URL parameter, default page is one
$page = isset($_GET['page']) ? $_GET['page'] : 1; 
 
// set number of records per page
$records_per_page = 5;
 
// calculate for the query LIMIT clause
$from_record_num = ($records_per_page * $page) - $records_per_page;
?>

Change paging.php code

The new paging.php code will look like the following.

<?php
echo "<ul class=\"pagination\">";
 
// 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>";
}
 
// count all products in the database to calculate total pages
$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><a href='" .$page_url . "page={$total_pages}' title='Last page is {$total_pages}.'>";
        echo "Last Page";
    echo "</a></li>";
}
 
echo "</ul>";
?>

Include core.php and read_template.php

The core.php file will be included at the beginning of index.php file. The read_template.php will be included before the layout_footer.php inclusion. The new index.php will look like the following code

<?php
// core.php holds pagination variables
include_once 'config/core.php';
 
// include database and object files
include_once 'config/database.php';
include_once 'objects/product.php';
include_once 'objects/category.php';
 
// instantiate database and product object
$database = new Database();
$db = $database->getConnection();
 
$product = new Product($db);
$category = new Category($db);
 
$page_title = "Read Products";
include_once "layout_header.php";
 
// query products
$stmt = $product->readAll($from_record_num, $records_per_page);
 
// specify the page where paging is used
$page_url = "index.php?";
 
// count total rows - used for pagination
$total_rows=$product->countAll();
 
// read_template.php controls how the product list will be rendered
include_once "read_template.php";
 
// layout_footer.php holds our javascript and closing html tags
include_once "layout_footer.php";
?>

Create search.php

This is the most important file of this section. This file will display the records based on a user's search term.

Create a new file and name it "search.php". Open that file and put the following code.

<?php
// core.php holds pagination variables
include_once 'config/core.php';
 
// include database and object files
include_once 'config/database.php';
include_once 'objects/product.php';
include_once 'objects/category.php';
 
// instantiate database and product object
$database = new Database();
$db = $database->getConnection();
 
$product = new Product($db);
$category = new Category($db);
 
// get search term
$search_term=isset($_GET['s']) ? $_GET['s'] : '';
 
$page_title = "You searched for \"{$search_term}\"";
include_once "layout_header.php";
 
// query products
$stmt = $product->search($search_term, $from_record_num, $records_per_page);
 
// specify the page where paging is used
$page_url="search.php?s={$search_term}&";
 
// count total rows - used for pagination
$total_rows=$product->countAll_BySearch($search_term);
 
// read_template.php controls how the product list will be rendered
include_once "read_template.php";
 
// layout_footer.php holds our javascript and closing html tags
include_once "layout_footer.php";
?>

Add search() and countAll_BySearch() methods

Open "product.php" file which is inside the "objects" folder. Add the following methods in the class.

// read products by search term
public function search($search_term, $from_record_num, $records_per_page){
 
    // select query
    $query = "SELECT
                c.name as category_name, p.id, p.name, p.description, p.price, p.category_id, p.created
            FROM
                " . $this->table_name . " p
                LEFT JOIN
                    categories c
                        ON p.category_id = c.id
            WHERE
                p.name LIKE ? OR p.description LIKE ?
            ORDER BY
                p.name ASC
            LIMIT
                ?, ?";
 
    // prepare query statement
    $stmt = $this->conn->prepare( $query );
 
    // bind variable values
    $search_term = "%{$search_term}%";
    $stmt->bindParam(1, $search_term);
    $stmt->bindParam(2, $search_term);
    $stmt->bindParam(3, $from_record_num, PDO::PARAM_INT);
    $stmt->bindParam(4, $records_per_page, PDO::PARAM_INT);
 
    // execute query
    $stmt->execute();
 
    // return values from database
    return $stmt;
}
 
public function countAll_BySearch($search_term){
 
    // select query
    $query = "SELECT
                COUNT(*) as total_rows
            FROM
                " . $this->table_name . " p 
            WHERE
                p.name LIKE ? OR p.description LIKE ?";
 
    // prepare query statement
    $stmt = $this->conn->prepare( $query );
 
    // bind variable values
    $search_term = "%{$search_term}%";
    $stmt->bindParam(1, $search_term);
    $stmt->bindParam(2, $search_term);
 
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
 
    return $row['total_rows'];
}

Output

php-mysql-oop-crud-tutorial

File Upload in PHP the OOP Way

In this section, we will add a "file upload" feature. This feature is included in the LEVEL 2 source code download.

Change HTML form

Open create_product.php and find the "form" tag. Change that line to the following code. The "enctype" enables the form to submit a file to the server.

<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post" enctype="multipart/form-data">

On the same HTML table, find the closing "tr" tag of the "Category" field. Add the following code. This adds an input field where the user can browse the file he wants to upload.

<tr>
    <td>Photo</td>
    <td><input type="file" name="image" /></td>
</tr>

Set value of "image" field

Open create_product.php and add the new "image" field. The value will be the file name of the submitted file. We used the built-in sha1_file() function the make the file name unique.

Open create_product.php file. Place the following code under $product->category_id = $_POST['category_id']; code.

$image=!empty($_FILES["image"]["name"])
        ? sha1_file($_FILES['image']['tmp_name']) . "-" . basename($_FILES["image"]["name"]) : "";
$product->image = $image;

Change create() method

Open "objects" folder and open the "product.php" file inside it. Find the "create()" method.

Add the "image" field by changing the query to:

// insert query
$query = "INSERT INTO " . $this->table_name . "
            SET name=:name, price=:price, description=:description,
                category_id=:category_id, image=:image, created=:created";

On the sanitize section, it will be:

$this->image=htmlspecialchars(strip_tags($this->image));

Then bind the value.

$stmt->bindParam(":image", $this->image);

Add the "image" property at the top of the class, maybe after public $category_id;

public $image;

Using the PhpMyAdmin, add an "image" field in the products table. Set the type to VARCHAR with 512 in length.

Call uploadPhoto() method

Open create_product.php and find this line.

// product was created in database
echo "<div class='alert alert-success'>Product was created.</div>";

Put the following code under the code above. This will call the uploadPhoto() method that will try to upload the file to server.

// try to upload the submitted file
// uploadPhoto() method will return an error message, if any.
echo $product->uploadPhoto();

Add uploadPhoto() method

The previous section will not work without the complete code of uploadPhoto() method.

Open "objects" folder and open the "product.php" file inside it. Add the following method inside the class.

// will upload image file to server
function uploadPhoto(){
 
    $result_message="";
 
    // now, if image is not empty, try to upload the image
    if($this->image){
 
        // sha1_file() function is used to make a unique file name
        $target_directory = "uploads/";
        $target_file = $target_directory . $this->image;
        $file_type = pathinfo($target_file, PATHINFO_EXTENSION);
 
        // error message is empty
        $file_upload_error_messages="";
 
    }
 
    return $result_message;
}

Validate submitted file

Now we will validate the submitted file by:

  • Identifying if it's a real or fake image.
  • Limit the allowed file types.
  • Prevent multiple file on the server.
  • Deny uploading files with large file size.
  • Making sure the "uploads" directory exists.

Add the following code after $file_upload_error_messages=""; of the previous section.

// make sure that file is a real image
$check = getimagesize($_FILES["image"]["tmp_name"]);
if($check!==false){
    // submitted file is an image
}else{
    $file_upload_error_messages.="<div>Submitted file is not an image.</div>";
}
 
// make sure certain file types are allowed
$allowed_file_types=array("jpg", "jpeg", "png", "gif");
if(!in_array($file_type, $allowed_file_types)){
    $file_upload_error_messages.="<div>Only JPG, JPEG, PNG, GIF files are allowed.</div>";
}
 
// make sure file does not exist
if(file_exists($target_file)){
    $file_upload_error_messages.="<div>Image already exists. Try to change file name.</div>";
}
 
// make sure submitted file is not too large, can't be larger than 1 MB
if($_FILES['image']['size'] > (1024000)){
    $file_upload_error_messages.="<div>Image must be less than 1 MB in size.</div>";
}
 
// make sure the 'uploads' folder exists
// if not, create it
if(!is_dir($target_directory)){
    mkdir($target_directory, 0777, true);
}

Return error messages

If the file is valid, we will upload the file to server. Specifically, in the "uploads" folder. If there's any error, we will return it to be shown to the user.

Place the following code after the previous section's code.

// if $file_upload_error_messages is still empty
if(empty($file_upload_error_messages)){
    // it means there are no errors, so try to upload the file
    if(move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)){
        // it means photo was uploaded
    }else{
        $result_message.="<div class='alert alert-danger'>";
            $result_message.="<div>Unable to upload photo.</div>";
            $result_message.="<div>Update the record to upload photo.</div>";
        $result_message.="</div>";
    }
}
 
// if $file_upload_error_messages is NOT empty
else{
    // it means there are some errors, so show them to user
    $result_message.="<div class='alert alert-danger'>";
        $result_message.="{$file_upload_error_messages}";
        $result_message.="<div>Update the record to upload photo.</div>";
    $result_message.="</div>";
}

Show uploaded image file

Open "objects" folder and open "product.php" file. Find readOne() method. Add the "image" field in the method. The new method should look like the following.

function readOne(){
 
    $query = "SELECT name, price, description, category_id, image
        FROM " . $this->table_name . "
        WHERE id = ?
        LIMIT 0,1";
 
    $stmt = $this->conn->prepare( $query );
    $stmt->bindParam(1, $this->id);
    $stmt->execute();
 
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
 
    $this->name = $row['name'];
    $this->price = $row['price'];
    $this->description = $row['description'];
    $this->category_id = $row['category_id'];
    $this->image = $row['image'];
}

Open read_one.php file and find the closing "tr" tag of the "Category" field in the HTML table. Add the following code. This will show the uploaded image.

echo "<tr>";
    echo "<td>Image</td>";
    echo "<td>";
        echo $product->image ? "<img src='uploads/{$product->image}' style='width:300px;' />" : "No image found.";
    echo "</td>";
echo "</tr>";

Output

Click the "Create" button, you will see something like the image below.

When you submitted the form, it will show a message prompt.

If you tried to upload an invalid image file, for example a PDF file. It will show an error message.

If you click the "Read" button of a record with an image, it will look like the following.

If the record has no image, it will say "No image found." message.

Download source codes

Download LEVEL 1 Source Code

FEATURES LEVEL 1
Object Oriented Programming Source Code YES
PDO extension used YES
Create product YES
Read product YES
Update product YES
Delete product YES
Price display with dollar sign YES
Pagination YES
Bootstrap UI YES
SQL file in "dev" folder YES
$20 - Download source code

Download LEVEL 2 Source Code

FEATURES LEVEL 2
All features of LEVEL 1 above YES
HTML5 (font-end) validation for create product YES
HTML5 (font-end) validation for update product YES
Category selection for create and update product. YES
Buttons with Glyphicons YES
Search products by name or description YES
HTML5 (font-end) validation for search product YES
Pagination in search YES
Allow user to input page number (read and search list) YES
Export / download records to CSV YES
Price display with dollar sign, comma and decimal point YES
Multiple delete YES
File upload field when creating or updating record YES
$40 - Download source code

Download LEVEL 3 Source Code

FEATURES LEVEL 3
All features of LEVEL 1 and 2 above YES
Bootstrap navigation bar YES
Select category in navigation YES
Higlight category in navigation YES
Create category YES
Read category YES
Update category YES
Delete category YES
View products by category YES
Pagination for category YES
Search category YES
Pagination for category search YES
Server side validation for create product & category YES
Server side validation for update product & category YES
Sorting by fields YES
Pagination for sorting by fields YES
jQuery UI enabled YES
Search product by date range - record date created YES
Pagination for earch product by date range YES
jQuery UI calendar for picking date YES
$50 - Download source code

How To Run The Source Codes?

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. Create your database using PhpMyAdmin, database name is "php_oop_crud_level_3" *
  3. Import the SQL file called "php_oop_crud_level_3.sql" located in the "dev" folder.
  4. You run index.php file. For example: http://localhost/php-oop-crud-level-3/index.php

* Database name and SQL file is different for LEVEL 1 and 2 source codes.

Why download the source codes?

Do you need more reasons to download it?

MORE REASONS TO DOWNLOAD THE CODE ALL
Use new skills for your multiple projects YES
Save huge amount of time learning Bootstrap and PHP YES
Code examples are direct to the point YES
Well explained and commented source code YES
Fast and friendly email support YES
Free source code updates YES

What's Next?

I hope you learned a lot from our PHP OOP CRUD Tutorial! Learning PHP Object Oriented Programming is fun and it can dramatically improve your career.

Up next: You have two choices.

A. Learn our PHP Login Script with Session Tutorial – Step by Step Guide! - Let's put our PHP OOP CRUD knowledge to work by building a simple PHP login script.

B. Learn How to create a simple REST API in PHP - Step by Step Guide! - this is required before we go to our JavaScript programming tutorials.

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!

Please note that this post is in continuous development, meaning I'll update it every now and then.

If you have a friend or know someone who needs this PHP OOP CRUD Tutorial, please share this page to them! I know you will help them a lot by doing it. Thanks!

Bootstrap Tutorial for Beginners – Step by Step Guide!

Bootstrap is a CSS framework that will make your web application look good, fast, and responsive. You won't have to worry about having a decent user interface when you use it.

I love Bootstrap because it solves a problem that I have. I'm not good at designing web app user interfaces. That is why I made this Bootstrap tutorial for beginners.

As proof, you will see that we are using Bootstrap in most of our tutorials. Here are some good looking websites or web apps built with the help of Bootstrap: http://expo.getbootstrap.com

Just a little history, Bootstrap was created on Twitter. It was called Twitter Bootstrap to streamline their development. Thanks to these people, the library is still in active development.

The following sections will be your step by step guide to your first web development with Bootstrap.

Include Bootstrap via CDN

We will use a CDN or Content delivery network to enable Bootstrap on our page.

Using Bootstrap CDN means that we will not download and store the bootstrap files in our server or local machine. We will just include the Bootstrap CSS and JavaScript links on our web page.

Write HTML5 boilerplate

Create new index.html file. Open the file, place the following code and save it.

<!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>Bootstrap Tutorial for Beginners</title>
 
    <!-- Bootstrap CSS will be here -->
</head>
<body>
 
<!-- navigation bar will be here -->
<!-- container bar will be here -->
 
<!-- Bootstrap JavaScript will be here -->
 
</body>
</html>

Our output on this section is a blank page. We do not have any contents inside the body tags. Comments are not displayed, of course.

But if we view the source, we actually made some progress!

Include Bootstrap CSS

On index.html file, replace <!-- Bootstrap CSS will be here --> with the following code.

<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

The integrity and crossorigin attributes are needed for security purposes. The answers in this question can explain it better.

Our output is still a blank page. All we can do for now is view the source to see if it was updated.

Include Bootstrap JavaScript

Bootstrap features like the navigation bar need the Bootstrap JavaScript file.

On index.html file, replace <!-- Bootstrap JavaScript will be here --> with the following code.

<!-- javascript for bootstrap -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
    integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous">
</script>
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
    integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous">
</script>
 
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
    integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous">
</script>

Output? Still a blank page. But let's view the source.

Add a navigation bar

Bootstrap Navbar, also called navigation header, is so cool. They look good on the desktop and on any mobile device. Your users won't get lost on your website if you use them properly.

On index.html file, replace <!-- navigation bar will be here --> with the following code.

<!-- navbar -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
        aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
 
    <!-- navigation links will be here -->
</nav>
<!-- /navbar -->

Output? Yes! This is the first time (in this tutorial) that we will see something on the page.

Add navigation links

On index.html file, replace <!-- navigation links will be here --> with the following code.

<div class="collapse navbar-collapse" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
            <a class="nav-link" href="index.html">Home <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="https://www.codeofaninja.com/2014/05/bootstrap-tutorial-beginners-step-step.html" target="_blank">Tutorial</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="https://www.codeofaninja.com" target="_blank">Blog</a>
        </li>
        <!-- drop down will be here -->
    </ul>
    <!-- search form will be here -->
</div>

Our output shows navigation links on the Navbar.

Add a drop down

On index.html file, replace <!-- drop down will be here --> with the following code.

<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
        data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Dropdown
    </a>
    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
        <a class="dropdown-item" href="#">Action</a>
        <a class="dropdown-item" href="#">Another action</a>
        <div class="dropdown-divider"></div>
        <a class="dropdown-item" href="#">Something else here</a>
    </div>
</li>

Our output shows a drop down on the Navbar. Cool!

Add a search form

On index.html file, replace <!-- search form will be here --> with the following code.

<form class="form-inline my-2 my-lg-0">
    <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
    <button class="btn btn-primary my-2 my-sm-0" type="submit">Search</button>
</form>

Output shows an input box and a search button on the upper right side corner of our page.

Add content container

A Bootstrap Container is required to make our web page responsive.

On index.html file, replace <!-- container will be here --> with the following code.

<div class="container mt-5">
    <!-- heading will be here -->
    <!-- alert will be here -->
    <!-- table will be here -->
</div>

You can replace the class container with a container-fluid if you want the container to have a full width.

Nothing has changed on our output. But if you will view the source, you can see the div tag with container class.

Add a heading

A Bootstrap Heading is important because it tells the user what page he was in.

On index.html file, replace <!-- heading will be here --> with the following code.

<div class="row">
    <div class="col-sm">
        <h1>Bootstrap Sample Page with Form</h1>
    </div>
</div>

As you may have noticed, we used a div tag with a row and then col-sm class. This class enables the Bootstrap Grid System. Grid systems are used for creating page layouts through a series of rows and columns that house your content.

Output shows our heading.

Add a table

Our Bootstrap Table will hold form elements like a text box. The Bootstrap table looks good and has hover effects as well.

On index.html file, replace <!-- table will be here --> with the following code.

<div class="row">
    <div class="col-sm">
         
        <table class='table table-hover'>
 
            <tr>
                <td>Name</td>
                <td></td>
            </tr>
 
            <tr>
                <td>Contact Number</td>
                <td></td>
            </tr>
 
            <tr>
                <td>Address</td>
                <td></td>
            </tr>
 
            <tr>
                <td>List</td>
                <td></td>
            </tr>
 
            <tr>
                <td></td>
                <td></td>
            </tr>
 
        </table>
             
    </div>
</div>

Our output shows a table with a few information.

Add form elements to a table

Our Bootstrap Form example will have a few text boxes, a text area, a select drop-down list and a submit button.

On index.html file, remove the code from opening <table> tag to closing </table> table. Replace it with the following code.

<form action='#' method='post'>
    <table class='table table-hover'>
 
        <tr>
            <td>Name</td>
            <td><input type='text' name='name' class='form-control' required></td>
        </tr>
 
        <tr>
            <td>Contact Number</td>
            <td><input type='text' name='contact_number' class='form-control' required></td>
        </tr>
 
        <tr>
            <td>Address</td>
            <td><textarea name='address' class='form-control'></textarea></td>
        </tr>
 
        <tr>
            <td>List</td>
            <td>
                <select name='list_id' class='form-control'>
                    <option value='1'>List One</option>
                    <option value='2'>List Two</option>
                    <option value='3'>List Three</option>
                </select>
            </td>
        </tr>
 
        <tr>
            <td></td>
            <td>
                <button type="submit" class="btn btn-primary">
                    <span class="glyphicon glyphicon-plus"></span> Submit
                </button>
            </td>
        </tr>
 
    </table>
</form>

Our output shows our HTML form.

Add an alert message

Bootstrap Alerts are a nice way to get your user's attention. Here's how to add a good looking alert message.

On index.html file, replace <!-- alert will be here --> with the following code.

<div class="row">
    <div class="col-sm">
        <div class="alert alert-success">
            <strong>Good day!</strong> This is an example alert. Visit <a href="https://codeofaninja.com/" target="_blank">codeofaninja.com</a>!
        </div>
    </div>
</div>

Output below shows an alert message.

To change alert colors, you may replace alert-success with alert-info, alert-danger or alert-warning.

Bootstrap Online Resources

What's Next?

Up Next: Learn jQuery Tutorial for Beginners – 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!

If you have a friend who need help and is getting started to learn Bootstrap, please share this article with them.

Is there anything else I can do to improve this post? Please share your thoughts on the comments section below.

Thanks for reading our bootstrap tutorial for beginners!

jQuery Tutorial for Beginners – Step By Step Guide!

jquery-step-by-step-tutorial-for-beginners

Previously, we learned how to use Bootstrap to make our web applications look good. This time, we will learn how to use jQuery.

Many of you asked me how to use jQuery. This tutorial is my answer to you. I want to give you links but I feel like it's easier to teach someone about something that is your own version of work! We hope you guys will find this step by step guide useful.

Getting Started with jQuery

What is jQuery? Okay here’s the simplest definition I can give. jQuery is a JavaScript library. It can:

  1. Make your JavaScript code shorter, faster and cross browser.
  2. Manipulate your HTML, like showing or hiding something from the page.
  3. Handles events – it can do something when a user click a button or any other activity a user can do with a mouse.
  4. Animation – for example make a part of your page fade in, fade out or just simply make something move.
  5. AJAX – do a server request without refreshing your whole web page.

This post. I assume you already know basic HTML, CSS and JavaScript. In this post, aside from the simple definition of jQuery above, we are just going to have two parts:

  1. The super straightforward, step by step tutorial or guide in running a very basic jQuery script. (2.0)
  2. We are going to take a look more of the jQuery basic concepts, as shown in #1 (3.0)

Run jQuery in 5 Easy Steps

Follow the steps below – these steps will lead you to run a very basic jQuery script that does a slide and toggle.

Create HTML page with its basic structure.

<!-- step 1 -->
<!DOCTYPE html>
<html>
<head>
    <title>jQuery Tutorial for Beginners</title>
</head>
<body>
 
</body>
</html>

Add element to be clicked. We’re gonna have a button in this example, we added an ID name to this button called myButton. Add the following code inside the "body" tag.

<!-- step 2 -->
<button id='myButton'>Click to Slide or Toggle</button>

Add the element to be shown or hidden. We’re gonna have a "p" tag with bunch of sample words inside. Add the following code below step 2′s code.

<!-- step 3 -->
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec.
</p>

Add the jQuery library. Aren’t you excited? You can also download your own copy of jQuery but in today’s example, we’ll be linking to Google’s copy of jQuery. Add the following code below step 3′s code.

<!-- step 4 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>

Step 5: Add jQuery script. This script will show or hide the "p" tag and the words inside it. Notice that we selected the button by referencing our button’s ID myButton.

<!-- step 5 -->
<script>
$("#myButton").click(function () {
    $("p").slideToggle("slow");
});
</script>

Download Source Codes

You can download all the code used in this tutorial for only $9.99 $5.55!

Congratulations! You are now a jQuery coder! Just kidding. Not yet. But don’t lose hope!

To achieve being a real jQuery coder, like any other skill, it must be practiced and be well versed with its concepts. So continue to read below and make your jQuery wisdom a little bit better.jQuery Basic Concepts

4.1 Run jQuery when DOM is ready. We didn’t implement this in our example above because I want to give you a quick look on how to run a jQuery script and it is a very small web page anyway.

But in reality, if you use jQuery in larger web pages, you have to run it when the DOM is ready. Here’s how:

$(document).ready(function() {
    // jQuery will run once everthing else in your web page is already loaded.
    // All your jQuery codes here.
});

How to Select an Element in jQuery? Learning jQuery selectors are very important because you’re dealing with HTML elements within your web page.

I’m gonna give you some of the most basic selectors being used:

// selects 'only one' HTML element with ID "myButton", such as our example above
// notice that we use hashes (#) for ids, like that of CSS
$("#myButton");
 
// selects all HTML elements with class "myClass", for instance: <div class='myClass'></div>
// notice that we used dots (.) for classes, like that of CSS
$(".myClass");
 
// selects all button HTML element, for example: <button>Click Me!</button>
$("button");
 
// selects all div element, example: <div>Me and all other div will be selected!</div>
$("div");
 
// selects all anchor link element, for example: <a href="https://codeofaninja.com/">Me and all other 'a' tags will be selected!</a>
$("a");

Learn more jQuery Selectors

jQuery Events. In our example above (2.0), we use a click event, in jQuery it was represented by the click() method. Here are some more jQuery events that you might find useful:

$("button").click(function(){
    // do something when user click the button
});
 
$("form").submit(function(){
    // do something when user submits a form
});
 
$("#myDiv").hover(function(){
    // do something when user hover an HTML element
});
 
$("#myTextbox").keyup(function(){
    // do something when user types on a textbox with ID myTextbox
});

Learn more jQuery Events

Animation Effects with jQuery. On our example above (2.0), the animation effect we used is the slideToggle(). Here are some other animations that you can do with jQuery:

// slide or toggle animation with a <p> tag
// you can change 'slow' to 'fast' or any number in milliseconds
$("p").slideToggle("slow");
 
$("p").slideToggle(1000, function() {  
    // do something when slide up or down animation is done
});
 
// hide the matched elements with a sliding motion.
$( "#book" ).slideUp( "slow", function() {
    // animation complete
});
 
// display or hide the matched elements by animating their opacity.
$( "#book" ).fadeToggle( "fast", function() {
    // animation complete
});

Learn more jQuery Animation Effect

Remember that the examples above are just some of the basics. Continue to practice, search and learn more in the process. And as always, thanks for reading!

5.0 Online Resources

6.0 What's Next?

Learn jQuery UI Tutorial for Beginners - Learn how to use date picker and other user interface interactions, effects, widgets, and themes built on top of the jQuery.

7.0 Related Tutorials

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

8.0 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 learning with our jQuery Tutorial for Beginners! Please share this tutorial to one of your friends if you have time.

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!

PHP CRUD Tutorial for Beginners – Step By Step Guide!

Previously, we learned how to run your first PHP script. This time, we will learn CRUD operations with PHP and MySQL. CRUD stands for Create, Read, Update and Delete database records.

Overview

This tutorial is for your if:

  • You need a high quality and updated reference for a PHP CRUD tutorial.
  • You need to learn how to do CRUD operations in PHP and MySQL.
  • You are beginner in this kind of PHP web programming.

Coding CRUD with PHP and MySQL is one of the basics. PHP web programmers must be able to code it with less effort. We can perform this task using any of the three PHP Database extensions:

  1. Using the MySQL extension.
  2. Using the MySQLi extension.
  3. Using the PDO extension.

PHP 5.5 deprecated the MySQL extension. It is not recommended to use these days.

If you are programming with PHP, you'll have to use either MySQLi (i means improved) or PDO extension.

With that in mind, we will use the PDO extension. It is the newest and actively developed way of programming these CRUD grids.

Project file structure

Our PHP CRUD tutorial will contain the following main files.

  • dev/products.sql – contains the database table structure and sample data used in this project. Once you created your database in PhpMyAdmin, you can import this file.
  • config/database.php – used for database connection and configuration.
  • create.php – used for creating a new record. It contains an HTML form where the user can enter details for a new record.
  • index.php – used for reading records from the database. It uses an HTML table to display the data retrieved from the MySQL database.
  • read_one.php – used for reading one or single record from database. It uses an HTML table to display the data retrieved from the MySQL database.
  • update.php – used for updating a record. It uses an HTML form which will be filled out with data based on the given “id” parameter.
  • delete.php – used for deleting a record. It accepts an “id” parameter and deletes the record with it. Once it execute the delete query, it will redirect the user to the index.php page.

Prepare the database

Create the database

On your PhpMyAdmin, create a database named "php_beginner_crud_level_1".

If you're not sure how to do it, please take a look at the following example. Follow only the "create database" part.

Create the database table

Next, run the following SQL code. This is to create our products database table. If you're not sure how to do this, take a look at this resource.

--
-- Table structure for table `products`
--

CREATE TABLE IF NOT EXISTS `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  `description` text NOT NULL,
  `price` double NOT NULL,
  `created` datetime NOT NULL,
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;

Dump sample data on the table

Again, run the following SQL code on your PhpMyAdmin. This will insert the sample data or record it on our products database table.

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

INSERT INTO `products` (`id`, `name`, `description`, `price`, `created`, `modified`) VALUES
(1, 'Basketball', 'A ball used in the NBA.', 49.99, '2015-08-02 12:04:03', '2015-08-06 06:59:18'),
(3, 'Gatorade', 'This is a very good drink for athletes.', 1.99, '2015-08-02 12:14:29', '2015-08-06 06:59:18'),
(4, 'Eye Glasses', 'It will make you read better.', 6, '2015-08-02 12:15:04', '2015-08-06 06:59:18'),
(5, 'Trash Can', 'It will help you maintain cleanliness.', 3.95, '2015-08-02 12:16:08', '2015-08-06 06:59:18'),
(6, 'Mouse', 'Very useful if you love your computer.', 11.35, '2015-08-02 12:17:58', '2015-08-06 06:59:18'),
(7, 'Earphone', 'You need this one if you love music.', 7, '2015-08-02 12:18:21', '2015-08-06 06:59:18'),
(8, 'Pillow', 'Sleeping well is important.', 8.99, '2015-08-02 12:18:56', '2015-08-06 06:59:18');

As you may have noticed, steps 1 and 2 are both SQL queries. Yes, they can run at the same time. But I wanted it to be on separate steps to emphasize those SQL queries' purpose.

Create database connection file

This section will answer the question: how to connect to MySQL database with PDO?

  • Create php-beginner-crud-level-1 folder and open it.
  • Create config folder and open it.
  • Create database.php file.
  • Place the following code inside it.
<?php
// used to connect to the database
$host = "localhost";
$db_name = "php_beginner_crud_level_1";
$username = "root";
$password = "";

try {
    $con = new PDO("mysql:host={$host};dbname={$db_name}", $username, $password);
}

// show error
catch(PDOException $exception){
    echo "Connection error: " . $exception->getMessage();
}
?>

Output

We have set up the database successfully! The only output we have so far is the database, database table, and sample records we set up via PhpMyAdmin.

Let's proceed to the next section below.

Create or insert record in PHP

HTML5 boilerplate for create.php

We use the Bootstrap user interface for this project. If you are not familiar with Bootstrap, please learn our Bootstrap Tutorial for Beginners.

  • Go back to php-beginner-crud-level-1 folder.
  • Create a new create.php file.
  • Place the code following code inside the create.php file.
<!DOCTYPE HTML>
<html>
<head>
    <title>PDO - Create a Record - PHP CRUD Tutorial</title>

    <!-- Latest compiled and minified Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />

</head>
<body>

    <!-- container -->
    <div class="container">

        <div class="page-header">
            <h1>Create Product</h1>
        </div>

    <!-- html form to create product will be here -->

    </div> <!-- end .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>

</body>
</html>

HTML form to input new record data

Now we are going to start answering the question: how to create a record with PDO?

The code below will create an HTML form with input fields that matches the fields in the database. Replace <!-- html form to create product will be here --> comment of the previous section with the following code.

<!-- PHP insert code will be here -->

<!-- html form here where the product information will be entered -->
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post">
	<table class='table table-hover table-responsive table-bordered'>
		<tr>
			<td>Name</td>
			<td><input type='text' name='name' class='form-control' /></td>
		</tr>
		<tr>
			<td>Description</td>
			<td><textarea name='description' class='form-control'></textarea></td>
		</tr>
		<tr>
			<td>Price</td>
			<td><input type='text' name='price' class='form-control' /></td>
		</tr>
		<tr>
			<td></td>
			<td>
				<input type='submit' value='Save' class='btn btn-primary' />
				<a href='index.php' class='btn btn-danger'>Back to read products</a>
			</td>
		</tr>
	</table>
</form>

Code to create a new record

We are still working on the create.php file. Once the user filled out the form and clicked the save button, the code below will save it to the MySQL database.

Replace <!-- PHP insert code will be here --> comment of the previous section with the following code.

<?php
if($_POST){

	// include database connection
	include 'config/database.php';

	try{

		// insert query
		$query = "INSERT INTO products SET name=:name, description=:description, price=:price, created=:created";

		// prepare query for execution
		$stmt = $con->prepare($query);

		// posted values
		$name=htmlspecialchars(strip_tags($_POST['name']));
		$description=htmlspecialchars(strip_tags($_POST['description']));
		$price=htmlspecialchars(strip_tags($_POST['price']));

		// bind the parameters
		$stmt->bindParam(':name', $name);
		$stmt->bindParam(':description', $description);
		$stmt->bindParam(':price', $price);

		// specify when this record was inserted to the database
		$created=date('Y-m-d H:i:s');
		$stmt->bindParam(':created', $created);

		// Execute the query
		if($stmt->execute()){
			echo "<div class='alert alert-success'>Record was saved.</div>";
		}else{
			echo "<div class='alert alert-danger'>Unable to save record.</div>";
		}

	}

	// show error
	catch(PDOException $exception){
		die('ERROR: ' . $exception->getMessage());
	}
}
?>

Output

Congrats! For the first time, we can now see an output on a web page. Go to this URL:

http://localhost/php-beginner-crud-level-1/create.php

You will see the output that looks like the following images.

When the user fills out the form.

When the user submitted the form.

A new record added to the database.

Read records in PHP

Basic HTML code for index.php

Create a new index.php file. We prepare this to read records from the database. It answers the question: how to read records with PDO?

Place the following code inside the index.php file.

<!DOCTYPE HTML>
<html>
<head>
	<title>PDO - Read Records - PHP CRUD Tutorial</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 -->
	<style>
	.m-r-1em{ margin-right:1em; }
	.m-b-1em{ margin-bottom:1em; }
	.m-l-1em{ margin-left:1em; }
	.mt0{ margin-top:0; }
	</style>

</head>
<body>

    <!-- container -->
    <div class="container">

        <div class="page-header">
            <h1>Read Products</h1>
        </div>

        <!-- PHP code to read records will be here -->

    </div> <!-- end .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>

<!-- confirm delete record will be here -->

</body>
</html>

Read records from the database

This time we will read records from the database.

Replace <!-- PHP code to read records will be here --> comment of the previous section with the following code.

<?php
// include database connection
include 'config/database.php';

// delete message prompt will be here

// select all data
$query = "SELECT id, name, description, price FROM products ORDER BY id DESC";
$stmt = $con->prepare($query);
$stmt->execute();

// this is how to get number of rows returned
$num = $stmt->rowCount();

// link to create record form
echo "<a href='create.php' class='btn btn-primary m-b-1em'>Create New Product</a>";

//check if more than 0 record found
if($num>0){

	// data from database will be here

}

// if no records found
else{
	echo "<div class='alert alert-danger'>No records found.</div>";
}
?>

Add HTML table with heading

This is the HTML table that will hold and display data from the database.

Replace // data from database will be here comment of the previous section with the following code.

//start table
echo "<table class='table table-hover table-responsive table-bordered'>";

	//creating our table heading
	echo "<tr>
		<th>ID</th>
		<th>Name</th>
		<th>Description</th>
		<th>Price</th>
		<th>Action</th>
	</tr>";

	// table body will be here

// end table
echo "</table>";

Add HTML table body

This part is where we will loop through the list of records from the database. This loop will create the rows of data on our HTML table.

Replace // table body will be here comment of the previous section with the following code.

// retrieve our table contents
// fetch() is faster than fetchAll()
// http://stackoverflow.com/questions/2770630/pdofetchall-vs-pdofetch-in-a-loop
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
	// extract row
	// this will make $row['firstname'] to
	// just $firstname only
	extract($row);

	// creating new table row per record
	echo "<tr>
		<td>{$id}</td>
		<td>{$name}</td>
		<td>{$description}</td>
		<td>${$price}</td>
		<td>";
			// read one record
			echo "<a href='read_one.php?id={$id}' class='btn btn-info m-r-1em'>Read</a>";

			// we will use this links on next part of this post
			echo "<a href='update.php?id={$id}' class='btn btn-primary m-r-1em'>Edit</a>";

			// we will use this links on next part of this post
			echo "<a href='#' onclick='delete_user({$id});'  class='btn btn-danger'>Delete</a>";
		echo "</td>";
	echo "</tr>";
}

Output

Go to this URL:

http://localhost/php-beginner-crud-level-1/index.php

You will see the records retrieved from the database. It will look like the image below.

Read one record in PHP

Basic HTML code for read_one.php

Create a new read_one.php file. This is where we will read and display the details of a single database record.

Place the following code inside the read_one.php file.

<!DOCTYPE HTML>
<html>
<head>
	<title>PDO - Read One Record - PHP CRUD Tutorial</title>

    <!-- Latest compiled and minified Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />

</head>
<body>

    <!-- container -->
    <div class="container">

        <div class="page-header">
            <h1>Read Product</h1>
        </div>

        <!-- PHP read one record will be here -->

        <!-- HTML read one record table will be here -->

	</div> <!-- end .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>

</body>
</html>

Read one record from the database

The following code is how we retrieve a single database record.

Replace <!-- PHP read one record will be here --> comment of the previous section with the following code.

<?php
// get passed parameter value, in this case, the record ID
// isset() is a PHP function used to verify if a value is there or not
$id=isset($_GET['id']) ? $_GET['id'] : die('ERROR: Record ID not found.');

//include database connection
include 'config/database.php';

// read current record's data
try {
	// prepare select query
	$query = "SELECT id, name, description, price FROM products WHERE id = ? LIMIT 0,1";
	$stmt = $con->prepare( $query );

	// this is the first question mark
	$stmt->bindParam(1, $id);

	// execute our query
	$stmt->execute();

	// store retrieved row to a variable
	$row = $stmt->fetch(PDO::FETCH_ASSOC);

	// values to fill up our form
	$name = $row['name'];
	$description = $row['description'];
	$price = $row['price'];
}

// show error
catch(PDOException $exception){
	die('ERROR: ' . $exception->getMessage());
}
?>

Display record details

The following HTML table will hold and display the details of a single database record.

Open read_one.php file.

Replace <!-- HTML read one record table will be here --> comment with the following code.

<!--we have our html table here where the record will be displayed-->
<table class='table table-hover table-responsive table-bordered'>
	<tr>
		<td>Name</td>
		<td><?php echo htmlspecialchars($name, ENT_QUOTES);  ?></td>
	</tr>
	<tr>
		<td>Description</td>
		<td><?php echo htmlspecialchars($description, ENT_QUOTES);  ?></td>
	</tr>
	<tr>
		<td>Price</td>
		<td><?php echo htmlspecialchars($price, ENT_QUOTES);  ?></td>
	</tr>
	<tr>
		<td></td>
		<td>
			<a href='index.php' class='btn btn-danger'>Back to read products</a>
		</td>
	</tr>
</table>

Output

To read one record from the database, try to click any Read button from our index.php file.

You can also go to this URL:

http://localhost/php-beginner-crud-level-1/read_one.php?id=9

You will see an output like the image below.

Update record in PHP

Basic HTML code for udpate.php

Create a new update.php file. We are preparing to update a selected record from the database.

This will answer the question: how to update a record with PDO?

Place the following code inside the new update.php file.

<!DOCTYPE HTML>
<html>
<head>
	<title>PDO - Update a Record - PHP CRUD Tutorial</title>

    <!-- Latest compiled and minified Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />

</head>
<body>

    <!-- container -->
    <div class="container">

        <div class="page-header">
            <h1>Update Product</h1>
        </div>

        <!-- PHP read record by ID will be here -->

        <!-- HTML form to update record will be here -->

    </div> <!-- end .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>

</body>
</html>

Read a record by ID parameter

We have to get the record ID and store it in the $id variable. We access the $_GET['id'] variable to do it.

What we are trying to do here is to get the related data based on the given record ID. This is the way to auto-fill the HTML form with existing data from the database.

Replace <!-- PHP read record by ID will be here --> comment of the previous section with the following code.

<?php
// get passed parameter value, in this case, the record ID
// isset() is a PHP function used to verify if a value is there or not
$id=isset($_GET['id']) ? $_GET['id'] : die('ERROR: Record ID not found.');

//include database connection
include 'config/database.php';

// read current record's data
try {
	// prepare select query
	$query = "SELECT id, name, description, price FROM products WHERE id = ? LIMIT 0,1";
	$stmt = $con->prepare( $query );

	// this is the first question mark
	$stmt->bindParam(1, $id);

	// execute our query
	$stmt->execute();

	// store retrieved row to a variable
	$row = $stmt->fetch(PDO::FETCH_ASSOC);

	// values to fill up our form
	$name = $row['name'];
	$description = $row['description'];
	$price = $row['price'];
}

// show error
catch(PDOException $exception){
	die('ERROR: ' . $exception->getMessage());
}
?>

HTML form to update a record

This form will show the data retrieved using the previous section's code.

We read a single record from the database, based on the given ID parameter.

Open update.php file. Replace <!-- HTML form to update record will be here --> comment with the following code.

<!-- PHP post to update record will be here -->

<!--we have our html form here where new record information can be updated-->
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"] . "?id={$id}");?>" method="post">
	<table class='table table-hover table-responsive table-bordered'>
		<tr>
			<td>Name</td>
			<td><input type='text' name='name' value="<?php echo htmlspecialchars($name, ENT_QUOTES);  ?>" class='form-control' /></td>
		</tr>
		<tr>
			<td>Description</td>
			<td><textarea name='description' class='form-control'><?php echo htmlspecialchars($description, ENT_QUOTES);  ?></textarea></td>
		</tr>
		<tr>
			<td>Price</td>
			<td><input type='text' name='price' value="<?php echo htmlspecialchars($price, ENT_QUOTES);  ?>" class='form-control' /></td>
		</tr>
		<tr>
			<td></td>
			<td>
				<input type='submit' value='Save Changes' class='btn btn-primary' />
				<a href='index.php' class='btn btn-danger'>Back to read products</a>
			</td>
		</tr>
	</table>
</form>

Code to update the record

The following code will save the changes in the database.

That is if the user changes some value on the form and hits the Save Changes button.

Replace <!-- PHP post to update record will be here --> comment of the previous section with the following code.

<?php

// check if form was submitted
if($_POST){

	try{

		// write update query
		// in this case, it seemed like we have so many fields to pass and
		// it is better to label them and not use question marks
		$query = "UPDATE products
					SET name=:name, description=:description, price=:price
					WHERE id = :id";

		// prepare query for excecution
		$stmt = $con->prepare($query);

		// posted values
		$name=htmlspecialchars(strip_tags($_POST['name']));
		$description=htmlspecialchars(strip_tags($_POST['description']));
		$price=htmlspecialchars(strip_tags($_POST['price']));

		// bind the parameters
		$stmt->bindParam(':name', $name);
		$stmt->bindParam(':description', $description);
		$stmt->bindParam(':price', $price);
		$stmt->bindParam(':id', $id);

		// Execute the query
		if($stmt->execute()){
			echo "<div class='alert alert-success'>Record was updated.</div>";
		}else{
			echo "<div class='alert alert-danger'>Unable to update record. Please try again.</div>";
		}

	}

	// show errors
	catch(PDOException $exception){
		die('ERROR: ' . $exception->getMessage());
	}
}
?>

Output

To update a database record, run the index.php file and click any Edit button.

Or, go to this URL:

http://localhost/php-beginner-crud-level-1/update.php?id=9

You will see the result like the images below.

Update record form.

Submitted form.

Changes in the database.

Delete record in PHP

Tell the user if record was deleted

This will tell the user if there is a deleted record after clicking the delete button and OK in the pop-up.

Open index.php file. Replace // delete message prompt will be here comment with the following code.

$action = isset($_GET['action']) ? $_GET['action'] : "";

// if it was redirected from delete.php
if($action=='deleted'){
	echo "<div class='alert alert-success'>Record was deleted.</div>";
}

JavaScript to confirm record deletion

The user clicks on the Delete button in index.php.

Next, he will verify the deletion by clicking OK on the pop-up.

That user activity will execute the following JavaScript code.

Open index.php file. Replace <!-- confirm delete record will be here --> comment with the following code.

<script type='text/javascript'>
// confirm record deletion
function delete_user( id ){

	var answer = confirm('Are you sure?');
	if (answer){
		// if user clicked ok,
		// pass the id to delete.php and execute the delete query
		window.location = 'delete.php?id=' + id;
	}
}
</script>

Delete record from the database

The code below will delete a record from the database using the given ID parameter.

This answers the question: how to delete a record with PDO?

Create a new delete.php file, place the following code and save it.

<?php
// include database connection
include 'config/database.php';

try {

	// get record ID
	// isset() is a PHP function used to verify if a value is there or not
	$id=isset($_GET['id']) ? $_GET['id'] : die('ERROR: Record ID not found.');

	// delete query
	$query = "DELETE FROM products WHERE id = ?";
	$stmt = $con->prepare($query);
	$stmt->bindParam(1, $id);

	if($stmt->execute()){
		// redirect to read records page and
		// tell the user record was deleted
		header('Location: index.php?action=deleted');
	}else{
		die('Unable to delete record.');
	}
}

// show error
catch(PDOException $exception){
	die('ERROR: ' . $exception->getMessage());
}
?>

Output

Once the user clicks any Delete button, it will show a confirmation pop-up.

If the user clicks the "OK" button, the record will be deleted from the database. It will tell the user via message prompt that the record was deleted.

The record is gone in the database as well.

Pagination in PHP

Please note that this is a bonus section and is not included in the LEVEL 1 source code download. We will have to add or remove some codes we've done above so that pagination will work.

Set pagination variables

The following variables are used to calculate the correct numbers for the LIMIT clause of our SELECT query.

We will see how our SELECT query will change later.

Place the following code below include 'config/database.php'; line of index.php file.

// PAGINATION VARIABLES
// page is the current page, if there's nothing set, default is page 1
$page = isset($_GET['page']) ? $_GET['page'] : 1;

// set records or rows of data per page
$records_per_page = 5;

// calculate for the query LIMIT clause
$from_record_num = ($records_per_page * $page) - $records_per_page;

Add LIMIT clause in SELECT query

This will enable paginated requests to the database. Still on the index.php file, change the following code from:

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

to:

// select data for current page
$query = "SELECT id, name, description, price FROM products ORDER BY id DESC
	LIMIT :from_record_num, :records_per_page";

$stmt = $con->prepare($query);
$stmt->bindParam(":from_record_num", $from_record_num, PDO::PARAM_INT);
$stmt->bindParam(":records_per_page", $records_per_page, PDO::PARAM_INT);
$stmt->execute();

Count total number of records

Counting the total number of records will help calculate the correct pagination numbers.

Below the closing table tag in the index.php file, add the following code.

// PAGINATION
// count total number of rows
$query = "SELECT COUNT(*) as total_rows FROM products";
$stmt = $con->prepare($query);

// execute query
$stmt->execute();

// get total rows
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$total_rows = $row['total_rows'];

Include paging file

Add the following code after the previous section's code.

// paginate records
$page_url="index.php?";
include_once "paging.php";

Why a $page_url variable is needed? Because we made paging.php re-usable. You can use it for other objects you want to paginate.

For example, you're trying to paginate your read_categories.php, you will need to do:

$page_url="read_categories.php?";

You will have to follow the code pattern of sections 10.1 to 10.3 when you use the paging.php file.

Create paging.php

Create a new paging.php file. Place the following code and save it.

<?php
echo "<ul class='pagination pull-left margin-zero mt0'>";

// first page button will be here

// clickable page numbers will be here

// last page button will be here

echo "</ul>";
?>

Add first page button

Replace // first page button will be here comment of the previous section with the following code.

// first page button
if($page>1){

	$prev_page = $page - 1;
	echo "<li>
		<a href='{$page_url}page={$prev_page}'>
			<span style='margin:0 .5em;'>«</span>
		</a>
	</li>";
}

Add clickable page numbers

Open paging.php file.

Replace // clickable page numbers will be here comment with the following code.

// clickable page numbers

// find out total pages
$total_pages = ceil($total_rows / $records_per_page);

// range of num links to show
$range = 1;

// 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='javascript::void();'>{$x}</a>
			</li>";
		}

		// not current page
		else {
			echo "<li>
				<a href='{$page_url}page={$x}'>{$x}</a> 
			</li>";
		}
	}
}

Add last page button

Open paging.php file.

Replace // last page button will be here comment with the following code.

// last page button
if($page<$total_pages){
	$next_page = $page + 1;

	echo "<li>
		<a href='{$page_url}page={$next_page}'>
			<span style='margin:0 .5em;'>»</span>
		</a>
	</li>";
}

Output

Run index.php file on the browser:

http://localhost/php-beginner-crud-level-1/index.php

You should see the pagination buttons like the images below.

Read records page 1.

Read records page 2.

File upload in PHP

Now we are going to add a file upload feature when creating a record.

Add HTML "file" field

Open the create.php file and scroll down to the form. Find the opening "form tag and enable the file upload by changing it to:

<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post" enctype="multipart/form-data">

Find the closing tr tag of the price field. Once found, add the following code after it.

<tr>
	<td>Photo</td>
	<td><input type="file" name="image" /></td>
</tr>

Add "image" field

Still in create.php file. Scroll up and change the insert SQL query.

It should look like the following code. The new image field will store the file name of the submitted file.

// insert query
$query = "INSERT INTO products
			SET name=:name, description=:description,
				price=:price, image=:image, created=:created";

// prepare query for execution
$stmt = $con->prepare($query);

$name=htmlspecialchars(strip_tags($_POST['name']));
$description=htmlspecialchars(strip_tags($_POST['description']));
$price=htmlspecialchars(strip_tags($_POST['price']));

// new 'image' field
$image=!empty($_FILES["image"]["name"])
		? sha1_file($_FILES['image']['tmp_name']) . "-" . basename($_FILES["image"]["name"])
		: "";
$image=htmlspecialchars(strip_tags($image));

// bind the parameters
$stmt->bindParam(':name', $name);
$stmt->bindParam(':description', $description);
$stmt->bindParam(':price', $price);
$stmt->bindParam(':image', $image);

// specify when this record was inserted to the database
$created=date('Y-m-d H:i:s');
$stmt->bindParam(':created', $created);

Using PhpMyAdmin, add an "image" field in the products table as well.

Set variables for file upload

We will start the code for the file upload feature. Find the following line in the create.php file.

echo "<div class='alert alert-success'>Record was saved.</div>";

Under the code above, we will add the following code.

The if($image){ code will verify if there's an uploaded image.

If there is, inside the if statement, we will set the initial variables needed for the file upload.

// now, if image is not empty, try to upload the image
if($image){

	// sha1_file() function is used to make a unique file name
	$target_directory = "uploads/";
	$target_file = $target_directory . $image;
	$file_type = pathinfo($target_file, PATHINFO_EXTENSION);

	// error message is empty
	$file_upload_error_messages="";

}

Make sure submitted file is a real image

Now we will start validating the submitted file. The code below will identify if the submitted file is a real or fake image.

Place the following code under $file_upload_error_messages=""; of the previous section.

// make sure that file is a real image
$check = getimagesize($_FILES["image"]["tmp_name"]);
if($check!==false){
	// submitted file is an image
}else{
	$file_upload_error_messages.="<div>Submitted file is not an image.</div>";
}

Make sure certain file types are allowed

The following code will limit the allowed file types. Place it under the code of the previous section.

// make sure certain file types are allowed
$allowed_file_types=array("jpg", "jpeg", "png", "gif");
if(!in_array($file_type, $allowed_file_types)){
	$file_upload_error_messages.="<div>Only JPG, JPEG, PNG, GIF files are allowed.</div>";
}

Make sure file does not exist

There's a very small chance that the submitted file name will be the same as the one that exists in the server. This is because of the sha1_file() method we used in section 10.2 above.

But just in case there's a file with the same name, tell the user. Place the following code after the previous section's code.

// make sure file does not exist
if(file_exists($target_file)){
	$file_upload_error_messages.="<div>Image already exists. Try to change file name.</div>";
}

Make sure submitted file is not too large

Uploading a very large photo is not recommended in this case. So we will set the file size limit to less than 1 MB. Place the following code after the code of the previous section.

// make sure submitted file is not too large, can't be larger than 1 MB
if($_FILES['image']['size'] > (1024000)){
	$file_upload_error_messages.="<div>Image must be less than 1 MB in size.</div>";
}

Make sure the 'uploads' folder exists

The "uploads" folder is where we will put the submitted file. Make sure it exists by using the following code. Place it under the code of the previous section.

// make sure the 'uploads' folder exists
// if not, create it
if(!is_dir($target_directory)){
	mkdir($target_directory, 0777, true);
}

Try to upload the file

The move_uploaded_file built-in PHP function will place the uploaded file on the server directory.

Place the following code under the previous section's code.

// if $file_upload_error_messages is still empty
if(empty($file_upload_error_messages)){
	// it means there are no errors, so try to upload the file
	if(move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)){
		// it means photo was uploaded
	}else{
		echo "<div class='alert alert-danger'>
			<div>Unable to upload photo.</div>
			<div>Update the record to upload photo.</div>
		</div>";
	}
}

// if $file_upload_error_messages is NOT empty
else{
	// it means there are some errors, so show them to user
	echo "<div class='alert alert-danger'>
		<div>{$file_upload_error_messages}</div>
		<div>Update the record to upload photo.</div>
	</div>";
}

Output

Form to create a product with file upload field.

When the form was submitted.

The "uploads" folder was created, with the uploaded file inside.

The file name was saved in the database.

Show uploaded image in PHP

Add image field in query

Open the read_one.php file and apply the following changes to the code.

Add image field to the $query variable. It should look like the following.

$query = "SELECT id, name, description, price, image FROM products WHERE id = ? LIMIT 0,1";

Add '$image' variable after the '$price' variable.

$image = htmlspecialchars($row['image'], ENT_QUOTES);

Add HTML image tag

Find the closing tr tag of the Price field in the HTML table and put the following code after it.

It will show the uploaded image or 'No image found.' if no image was uploaded.

<tr>
	<td>Image</td>
	<td>
	<?php echo $image ? "<img src='uploads/{$image}' style='width:300px;' />" : "No image found.";  ?>
	</td>
</tr>

Output

Click the Read One button of the record we created with a file upload.

You should see something like the images below.

Record with an image.

Record without image.

Download Source Codes

Download LEVEL 1 Source Code

FEATURES LEVEL 1
PDO extension used YES
Create product YES
Read product YES
Update product YES
Delete product YES
Price display with dollar sign YES
SQL file in "dev" folder YES
$20 - Download now

Download LEVEL 2 Source Code

FEATURES LEVEL 2
All features of LEVEL 1 above YES
HTML5 (font-end) validation for create product YES
HTML5 (font-end) validation for update product YES
Category selection for create and update product. YES
Bootstrap UI YES
Buttons with Glyphicons YES
Pagination YES
Search products by name or description YES
HTML5 (font-end) validation for search product YES
Pagination in search YES
Allow user to input page number (read and search list) YES
Export / download records to CSV YES
Price display with dollar sign, comma and decimal point YES
Multiple delete YES
Create & update record with file upload YES
$40 - Download now

Download LEVEL 3 Source Code

FEATURES LEVEL 3
All features of LEVEL 1 and 2 above YES
Bootstrap navigation bar YES
Select category in navigation YES
Higlight category in navigation YES
Create category YES
Read category YES
Update category YES
Delete category YES
View products by category YES
Pagination for category YES
Search category YES
Pagination for category search YES
Server side validation for create product & category YES
Server side validation for update product & category YES
Sorting by fields YES
Pagination for sorting by fields YES
jQuery UI enabled YES
Search product by date range - record date created YES
Pagination for earch product by date range YES
jQuery UI calendar for picking date YES
$50 - Download now

Why download?

Do you need more reasons to download it?

MORE REASONS TO DOWNLOAD THE CODE ALL
Use new skills for your multiple projects YES
Save huge amount of time learning Bootstrap and PHP YES
Code examples are direct to the point YES
Well explained and commented source code YES
Fast and friendly email support YES
Free source code updates YES

How To Run The Source Code?

We highly recommend you 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 them.

  1. Extract the files to your server directory.
  2. Create your database using PhpMyAdmin, database name is "php_beginner_crud_3" - if you downloaded our LEVEL 3 source code.
  3. Import the SQL file called "php_beginner_crud_3.sql" located in the "dev" folder.
  4. You run index.php on the browser.

If you have any more questions, please feel free to contact me now. You can do it by sending a message to our email [email protected]

Thanks for supporting our website and projects here at codeofaninja.com!

Online Resources

What's Next?

After learning from this PHP CRUD tutorial, we can go one step higher. We can do this by learning object-oriented programming (OOP) in PHP.

Object-oriented programming (OOP) is a programming language model organized around objects rather than "actions" and data rather than logic. This is very exciting.

To learn more, we created the next tutorial just for you! Let's go and learn:
PHP, MySQL, and OOP CRUD Tutorial - Step by Step Guide!

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!

Please share this post if you think this is a useful PHP CRUD Tutorial. We hope you mastered how to create, read, update and delete database records and more. Thanks for learning here in codeofaninja.com!

How to display Facebook page events on website using PHP?

Do you want to learn how to display Facebook page events on your website? What if there's a way to create an event once, and then let it appear both on your website and Facebook page?

Today we're gonna talk about how to display publicly available Facebook Page events on your website. This one is great if you want your Facebook page events to be shown on your website in a synchronized way.

Once you created or updated an event on Facebook, it will be automatically reflected on your website too.

Don't want to code?

By the way, if you realized you do not want to code and you need more features, you can use a website plugin called SociableKIT.

You can easily customize the look and feel of your Facebook page posts feed and embed it on your website within a few clicks. See a tutorial here.

But if you like coding, continue with our tutorial below!

Overview

Here's an overview of what our code does:

Gets events listed with data such as event image, name, time, description, etc. from your Facebook fan page without using any Facebook PHP SDK, just the Facebook Graph API!

Display these event data to a webpage (assuming it is your WordPress or PHP website.)

Show some awesome UI powered by Bootstrap. If you’re not yet familiar with this awesome front-end framework, see our step-by-step Bootstrap tutorial here.

Final output

We have to know where we are going. If we completed the tutorial below, we will achieve the following output in the video below.

Create the index page

Create index.php file

This page is what will be loaded on the browser. Create index.php file. Put the following basic HTML 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>Display Facebook page events on website</title>

    <!-- CSS will be here -->
 
</head>
<body>

    <!-- Container will be here -->

</body>
</html>

CSS code

We're going to use Bootstrap to make our page look good. We'll also put some custom CSS. Replace <!-- CSS will be here --> with the following code.

<!-- CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link rel="stylesheet" href="custom.css" media="screen">

Create custom.css

These are just some additional customization for our user interface. Create a custom.css file. Put the following code.

.page-header{
    margin:30px 0;
}

.nav{
    margin-bottom:30px;
}

.event_item{
    margin-bottom:50px;
}

Container code

These divs have Bootstrap classes. It will contain our Facebook page events. Replace <!-- Container will be here --> with the following code.

<div class="container">
    <div class='col-lg-12'>
        <h1 class='page-header'>Display Facebook page events on website</h1>
        
        <!-- PHP code will be here -->

    </div>
</div>

PHP code

The code below gets the parameter from the URL about what to display. By default, it is "upcoming" events. The navigation.php file will help the user to select upcoming or past events.

The fb_page_events.php file will contain our request to the Facebook Graph API. Replace <!-- PHP code will be here --> with the following code.

<?php 
$display = isset($_GET["display"]) ? $_GET["display"] : "upcoming";
include "navigation.php";
include "fb_page_events.php";
?>

Create navigation.php file

This file will show two tabs that will allow our users to select upcoming or past events. Create a navigation.php file and put the following code.

<?php 
$upcoming_class_active = $display=="upcoming" ? "active" : "";
$past_class_active = $display=="past" ? "active" : "";

echo "<ul class='nav nav-tabs'>
    <li class='nav-item'>
        <a class='nav-link {$upcoming_class_active}' href='index.php'>Upcoming Events</a>
    </li>
    <li class='nav-item'>
        <a class='nav-link {$past_class_active}' href='index.php?display=past'>Past Events</a>
    </li>
</ul>";
?>

Display Facebook page events

Create fb_page_events.php file

This file will contain the process of building a request to the Facebook Graph API. Create fb_page_events.php file. Put the following code.

<?php 
// specify date range will be here

// unix timestamp format will be here

// request parameters will be here

// build the api request will be here

// sort to display upcoming events will be here

// looping through events will be here
?>

Specify date range

The code below identifies the "since" and "until" dates that will be used for the API request. For upcoming events, the "since" date is the date today and the "until" date is two years from today.

For past events, the "since" date is the date from two years ago and the "until" date is the date yesterday.

Replace <!-- specify date range will be here --> with the following code.

// specify date range
$year_range = 2;

if($display=="upcoming"){
	// date range for upcoming events
	$since_date = date('Y-m-d');
	$until_date = date('Y-12-31', strtotime('+' . $year_range . ' years'));
}

else{
	// date range for past events
	$since_date = date('Y-01-01', strtotime('-' . $year_range . ' years'));
	$until_date = date('Y-m-d', strtotime('-1 day'));
}

Convert to unix timestamp

Unix timestamp is required by the Facebook Graph API. We will convert the since and until dates using the code below. Replace <!-- unix timestamp format will be here --> with the following code.

// unix timestamp format
$since_unix_timestamp = strtotime($since_date);
$until_unix_timestamp = strtotime($until_date);

Specify request parameters

The variables below are needed to complete the parameters needed for the Facebook Graph API request. Replace <!-- request parameters will be here --> with the following code.

// request parameters
$api_version = "v11.0";
$fb_page_id = "YOUR_FACEBOOK_PAGE_ID";
$access_token="YOUR_PAGE_ACCESS_TOKEN";
$fields="id,name,description,place,timezone,start_time,cover";

Specify your Facebook page ID and access token

You need to replace YOUR_PAGE_ID and YOUR_PAGE_ACCESS_TOKEN with your own.

To get your Facebook page ID, follow this tutorial. To get your Facebook page access token, follow this tutorial.

We can do this process for you but there will be a service fee of $50. Also, you will need to make us an admin of your Facebook page.

If you want to avail of this service, pay using this link. After the payment, you will receive further instructions from [email protected]

Build the API request

The code below completes the API request link and get the response using file_get_contents() function. We will also decode the response so we can easily retrieve the data. Replace <!-- build the api request will be here --> with the following code.

// build the api request
$json_link = "https://graph.facebook.com/{$api_version}/{$fb_page_id}/events/attending/?fields={$fields}&access_token={$access_token}&since={$since_unix_timestamp}&until={$until_unix_timestamp}";
$json = file_get_contents($json_link);
$obj = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);

// for those using PHP version older than 5.4, use this instead:
// $obj = json_decode(preg_replace('/("\w+"):(\d+)/', '\\1:"\\2"', $json), true);

Sort to display upcoming events

Sorting is needed to properly display the upcoming events. The code below will let the upcoming events to be displayed from the date nearest to today up to the farthest date. Replace <!-- sort to display upcoming events will be here --> with the following code.

// sort to display upcoming events
if($display=="upcoming"){
	function sortFunction($a,$b){
		if ($a['start_time'] == $b['start_time']) return 0;
		return strtotime($a['start_time']) - strtotime($b['start_time']);
	}
	usort($obj['data'],"sortFunction");
}

Loop through events

The code below will loop through each events returned from the Facebook Graph API. Replace <!-- looping through events will be here --> with the following code.

// looping through events
foreach($obj['data'] as $event){
	include "extract_values.php";
	include "display_values.php";
}

Extract and display events data

Create extract_values.php file

In this file, we will extract different types of event data. Create extract_values.php file. Put the following code.

<?php 
// start date and time will be here

// basic info will be here

// location will be here
?>

Extract date and time

The code below will let us get the event's start date and time. Replace <!-- start date and time will be here --> with the following code.

// start date and time
$timezone=isset($event['timezone']) ? $event['timezone'] : "America/Los_Angeles";
date_default_timezone_set($timezone);

$start_date = date( 'l, F d, Y', strtotime($event['start_time']));

// in my case, I had to subtract 9 hours to sync the time set in facebook
$start_time = date('g:i a', strtotime($event['start_time']));

Extract basic information

The code below will let us get the event ID, name, description, and thumbnail. Replace <!-- basic info will be here --> with the following code.

// basic info
$eid = $event['id'];
$name = $event['name'];
$description = isset($event['description']) ? $event['description'] : "";
$pic_big = isset($event['cover']['source']) ? $event['cover']['source'] : "https://graph.facebook.com/{$api_version}/{$fb_page_id}/picture?type=large";

Extract location

Here we will get the event's complete address or location. Replace <!-- location will be here --> with the following code.

// location
$place_name = isset($event['place']['name']) ? $event['place']['name'] : "";
$city = isset($event['place']['location']['city']) ? $event['place']['location']['city'] : "";
$country = isset($event['place']['location']['country']) ? $event['place']['location']['country'] : "";
$zip = isset($event['place']['location']['zip']) ? $event['place']['location']['zip'] : "";

$location="";

if($place_name){ $location.="{$place_name}"; }
if($city){ $location.= $location ? ", {$city}" : "{$city}"; }
if($country){ $location.= $location ? ", {$country}" : "{$country}"; }
if($zip){ $location.= $location ? ", {$zip}" : "{$zip}"; }

if(empty($location)){
    $location="Location not set.";
}

$complete_event_add="{$location}";

Create display_values.php

The code below will let us display an event item with data we extracted earlier. Create display_values.php file. Put the following code.

<?php 
echo "<div class='row event_item'>
    <div class='col'>
        <img src='{$pic_big}' class='card-img-top' alt='...'>
    </div>
    <div class='col'>
        <h2 class='card-title'>{$name}</h2>
        <p class='card-text'>
        {$start_date} at {$start_time}
        </p>

        <p class='card-text'>
        {$complete_event_add}
        </p>

        <p class='card-text'>
        {$description}
        </p>
        <a href='https://www.facebook.com/events/{$eid}/' target='_blank' class='btn btn-primary'>More info</a>
    </div>
</div>";
?>

What People Say About This Code?

I'm so glad that other people are delighted by this code, here are some of them!

From Blog Comments

★★★★★ "Hi Mike, amazing tutorial." ~ simonerama

★★★★★ "Hello and THANK you for this amazing work! :)" ~ Sergio

★★★★★ "Did the trick for me. Thanks for the nice script!" ~ n0Fear

★★★★★ "Hi Mike, thanks for the great script. I'm a programming novice, but got this running the way I wanted to pretty quickly. I owe you a beer." ~ Bas Koole

★★★★★ "Hi it's working great :)" ~ Sebastian

From Emails

★★★★★ "I've got it working! You're a great man, will do some ad for you!" ~ Markus

★★★★★ "Hi Mike! BOOM, works great! Thanks again!" ~ Nick

★★★★★ "Perfect! Thank you very much! If I have some new jobs, I will contact you! Greetings from Germany." ~ Eric

★★★★★ "Thank you for the fast reply, yes this should work for me. I will contact you again. Thank you so much." ~ Ruocco

From Facebook Messages

★★★★★ "Hey Mate, code's a lifesaver (and time saver!)" ~ Andrew

★★★★★ "Thanks, I've been trying to get Facebook events on the website for 6+ months had no luck, decided last night to update the site which I haven't done in a while and thought I'd give it another go and found you're page through a google search." ~ Ward

★★★★★ "Mike it's great and simple! I like! Thank you!" ~ Jasmin

★★★★★ "You're a life saver, thanks so much." ~ Brendon

Download the Complete 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, or income you can get from your website project or business.

For a limited time only, I will give you the source code for a low price. Download the source code by clicking the green buy button below.

FEATURES BASIC
Manage events for your Facebook Page and website once Yes
Save time figuring out and coding these features on your website Yes
Display list of all events Yes
Display list of upcoming events Yes
Display list of past events Yes
Display event cover photo (profile picture if none) Yes
Display event title Yes
Display event date and time Yes
Display event location Yes
Display event description Yes
Link to actual Facebook page event (opens in new tab) Yes
Bootstrap UI enabled Yes
Responsive layout (great for mobile devices) Yes
Free email support for 6 months. Yes
Free source code updates. Yes
$50 - Download now

Do you need more reasons to download it?

MORE REASONS TO GET IT
Buy only once, use up to 10 websites and Facebook pages! Yes
No different kind of licenses. Yes
No monthly or any recurring fees. Yes
No need to rely on another website to render Facebook page events. Yes
No need for codes from other websites. Yes
You can learn more how to code, I love teaching and can give you free tips! Yes
Familiarize yourself with the Facebook Graph API. Yes
Tutorial above is always free. Yes
Completely customizable. Yes

Thank you for supporting our projects!

What's Next?

Today we have learned how to show your Facebook page events on your website.

Did you know that you can also display Facebook photo albums and photos on your website?

Let us go to the next tutorial: How to display Facebook page photo album on website?

Related Source Codes

We have more tutorials related to social media APIs. 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 visiting our tutorial on how to display Facebook page events on website using PHP and Facebook Graph API!