Skip to main content

Make Food Ordering Website with PHP & MySQL

In our previous PHP project tutorial, we have developed Online Exam System with PHP and MySQL. In this tutorial, we will develop Food Ordering Website with PHP and MySQL.

The Online Food Order websites are very popular as it connect with different restaurants and customers. The websites enables restaurants to manage food foods and customers can make food order online.

So here in this tutorial, we develop a complete Food Ordering Website Project. The project contains an Admin section from where administrator can manage food items and front-end for customer side to list food items and make order.

Here we will cover following.

Admin End:

  • Manage Customer.
  • Manage Food Items.
  • Manage Orders.
  • Manage Users

Frond End:

  • List Food Items
  • Add Items to Cart.
  • Manage Cart.
  • Checkout Order

So Lets start developing webite.

Step1: Create Database Tables

First we will create MySQL database food_order_website and then create tables with data using below queries.

--
-- Database: `food_order_website`
--

-- --------------------------------------------------------

--
-- Table structure for table `food_customer`
--

CREATE TABLE `food_customer` (
  `id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `password` varchar(50) NOT NULL,
  `phone` varchar(50) NOT NULL,
  `address` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- Table structure for table `food_items`
--

CREATE TABLE `food_items` (
  `id` int(30) NOT NULL,
  `name` varchar(30) NOT NULL,
  `price` int(30) NOT NULL,
  `description` varchar(200) NOT NULL,
  `images` varchar(200) NOT NULL,
  `status` varchar(10) NOT NULL DEFAULT 'ENABLE'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- --------------------------------------------------------

--
-- Table structure for table `food_orders`
--

CREATE TABLE `food_orders` (
  `id` int(30) NOT NULL,
  `item_id` int(30) NOT NULL,
  `name` varchar(30) NOT NULL,
  `price` int(30) NOT NULL,
  `quantity` int(30) NOT NULL,
  `order_date` date NOT NULL,
  `order_id` varchar(50) NOT NULL,
  `userid` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `user`
--

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(250) NOT NULL,
  `email` varchar(50) NOT NULL,
  `password` varchar(50) NOT NULL,
  `role` enum('admin','user') NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


--
-- Indexes for dumped tables
--

--
-- Indexes for table `food_customer`
--
ALTER TABLE `food_customer`
  ADD PRIMARY KEY (`id`);

--
-- Indexes for table `food_items`
--
ALTER TABLE `food_items`
  ADD PRIMARY KEY (`id`);

--
-- Indexes for table `food_orders`
--
ALTER TABLE `food_orders`
  ADD PRIMARY KEY (`id`);

--
-- Indexes for table `user`
--
ALTER TABLE `user`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `food_customer`
--
ALTER TABLE `food_customer`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;

--
-- AUTO_INCREMENT for table `food_items`
--
ALTER TABLE `food_items`
  MODIFY `id` int(30) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=81;

--
-- AUTO_INCREMENT for table `food_orders`
--
ALTER TABLE `food_orders`
  MODIFY `id` int(30) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15;

--
-- AUTO_INCREMENT for table `user`
--
ALTER TABLE `user`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
COMMIT;

Step2: Manage Customer – Admin Section

We will implement customer module to manage customer. We will create file customer.php and list customer records.

<div class="row row-offcanvas row-offcanvas-left">
	<?php include('left_menus.php'); ?>
	<div class="col-md-9 col-lg-10 main"> 
	<h2>Customer List</h2>
	<div class="panel-heading">
		<div class="row">
			<div class="col-md-10">
				<h3 class="panel-title"></h3>
			</div>
			<div class="col-md-2" align="right">
				<button type="button" id="addCustomer" class="btn btn-info" title="Add Customer"><span class="glyphicon glyphicon-plus">Add</span></button>
			</div>
		</div>
	</div>			
	<table id="customerListing" class="table table-striped table-bordered">
		<thead>
			<tr>						
				<th>Sn.</th>					
				<th>Name</th>					
				<th>Email</th>
				<th>Phone</th>	
				<th>Address</th>						
				<th></th>
				<th></th>					
			</tr>
		</thead>
	</table>				
	</div>
</div>	

we will make initialize jQuery Datatables and make ajax request to customer_action.php with action listCustomer to load customer list.

var customerRecords = $('#customerListing').DataTable({
	"lengthChange": false,
	"processing":true,
	"serverSide":true,		
	"bFilter": false,		
	'serverMethod': 'post',		
	"order":[],
	"ajax":{
		url:"customer_action.php",
		type:"POST",
		data:{action:'listCustomer'},
		dataType:"json"
	},
	"columnDefs":[
		{
			"targets":[0, 4, 5],
			"orderable":false,
		},
	],
	"pageLength": 10
});	

we will check for action listCustomer and call method listCustomer() from Customer.php class.

$customer = new Customer($db);

if(!empty($_POST['action']) && $_POST['action'] == 'listCustomer') {
	$customer->listCustomer();
}

Now we will implement method listCustomer() in class Customer.php to return customer json data to list.

public function listCustomer(){	
		
	$sqlQuery = "SELECT id, name, email, password, phone, address
		FROM ".$this->customerTable." ";			
		
	if(!empty($_POST["search"]["value"])){
		$sqlQuery .= ' WHERE (id LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR email LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR phone LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR address LIKE "%'.$_POST["search"]["value"].'%" ';			
	}
	
	if(!empty($_POST["order"])){
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY id DESC ';
	}
	
	if($_POST["length"] != -1){
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}	
	
	$stmt = $this->conn->prepare($sqlQuery);
	$stmt->execute();
	$result = $stmt->get_result();	
	
	$stmtTotal = $this->conn->prepare($sqlQuery);
	$stmtTotal->execute();
	$allResult = $stmtTotal->get_result();
	$allRecords = $allResult->num_rows;
	
	$displayRecords = $result->num_rows;
	$records = array();	
	$count = 1;
	while ($customer = $result->fetch_assoc()) { 				
		$rows = array();			
		$rows[] = $count;
		$rows[] = ucfirst($customer['name']);
		$rows[] = $customer['email'];	
		$rows[] = $customer['phone'];	
		$rows[] = $customer['address'];			
		$rows[] = '<button type="button" name="update" id="'.$customer["id"].'" class="btn btn-warning btn-xs update"><span class="glyphicon glyphicon-edit" title="Edit">Edit</span></button>';
		$rows[] = '<button type="button" name="delete" id="'.$customer["id"].'" class="btn btn-danger btn-xs delete" ><span class="glyphicon glyphicon-remove" title="Delete">Delete</span></button>';
		$records[] = $rows;
		$count++;
	}
	
	$output = array(
		"draw"	=>	intval($_POST["draw"]),			
		"iTotalRecords"	=> 	$displayRecords,
		"iTotalDisplayRecords"	=>  $allRecords,
		"data"	=> 	$records
	);
	
	echo json_encode($output);
}	

Step3: Manage Food Items – Admin Section

We will implement functionality to manage foods. We will create file food.php and list customer.

<div class="row row-offcanvas row-offcanvas-left">
	<?php include('left_menus.php'); ?>
	<div class="col-md-9 col-lg-10 main"> 
	<h2>Food Items</h2>
	<div class="panel-heading">
		<div class="row">
			<div class="col-md-10">
				<h3 class="panel-title"></h3>
			</div>
			<div class="col-md-2" align="right">
				<button type="button" id="addFood" class="btn btn-info" title="Add Food"><span class="glyphicon glyphicon-plus">Add</span></button>
			</div>
		</div>
	</div>			
	<table id="foodListing" class="table table-striped table-bordered">
		<thead>
			<tr>						
				<th>Sn.</th>					
				<th>Name</th>
				<th>Image</th>						
				<th>price</th>
				<th>Description</th>												
				<th></th>
				<th></th>					
			</tr>
		</thead>
	</table>				
	</div>
</div>	

we will intialize jQuery Datatables and make ajax request to food_action.php with action listFood to list food items.

var foodRecords = $('#foodListing').DataTable({
	"lengthChange": false,
	"processing":true,
	"serverSide":true,		
	"bFilter": false,		
	'serverMethod': 'post',		
	"order":[],
	"ajax":{
		url:"food_action.php",
		type:"POST",
		data:{action:'listFood'},
		dataType:"json"
	},
	"columnDefs":[
		{
			"targets":[0, 4, 5],
			"orderable":false,
		},
	],
	"pageLength": 10
});	

we will check for action listFood and call listFoodItem() method from class Food.php.

$food = new Food($db);

if(!empty($_POST['action']) && $_POST['action'] == 'listFood') {
	$food->listFoodItem();
}

we will implement method listFoodItem() in class Food.php to list item.

public function listFoodItem(){		
		
	$sqlQuery = "SELECT id, name, price, description,images
		FROM ".$this->foodTable." ";			
		
	if(!empty($_POST["search"]["value"])){
		$sqlQuery .= ' WHERE (id LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR price LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR description LIKE "%'.$_POST["search"]["value"].'%" ';			
	}
	
	if(!empty($_POST["order"])){
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY id DESC ';
	}
	
	$stmtTotal = $this->conn->prepare($sqlQuery);
	$stmtTotal->execute();
	$allResult = $stmtTotal->get_result();
	$allRecords = $allResult->num_rows;
	
	if($_POST["length"] != -1){
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}	
	
	$stmt = $this->conn->prepare($sqlQuery);
	$stmt->execute();
	$result = $stmt->get_result();	
	
	
	
	$displayRecords = $result->num_rows;
	$records = array();	
	$count = 1;
	while ($food = $result->fetch_assoc()) { 				
		$rows = array();			
		$rows[] = $count;
		$rows[] = ucfirst($food['name']);
		$rows[] = '<img src="../images/'.$food["images"].'" width="50" height="50">';		
		$rows[] = "$".$food['price'];	
		$rows[] = $food['description'];					
		$rows[] = '<button type="button" name="update" id="'.$food["id"].'" class="btn btn-warning btn-xs update"><span class="glyphicon glyphicon-edit" title="Edit">Edit</span></button>';
		$rows[] = '<button type="button" name="delete" id="'.$food["id"].'" class="btn btn-danger btn-xs delete" ><span class="glyphicon glyphicon-remove" title="Delete">Delete</span></button>';
		$records[] = $rows;
		$count++;
	}
	
	$output = array(
		"draw"	=>	intval($_POST["draw"]),			
		"iTotalRecords"	=> 	$displayRecords,
		"iTotalDisplayRecords"	=>  $allRecords,
		"data"	=> 	$records
	);
	
	echo json_encode($output);
}	

Step4: Manage Orders – Admin Section

We will implement functionality to manage orders. We will create order.php file to list orders.

<div class="panel-heading">
	<div class="row">
		<div class="col-md-10">
			<h3 class="panel-title"></h3>
		</div>
		<div class="col-md-2" align="right">
			<button type="button" id="addOrder" class="btn btn-info" title="Add Order"><span class="glyphicon glyphicon-plus">Add</span></button>
		</div>
	</div>
</div>			
<table id="orderListing" class="table table-striped table-bordered">
	<thead>
		<tr>						
			<th>Sn.</th>					
			<th>Order</th>					
			<th>Date</th>
			<th>Customer</th>						
			<th></th>
			<th></th>					
		</tr>
	</thead>
</table>

We will make ajax request to order_action.php with action listOrder to list order record.

var orderRecords = $('#orderListing').DataTable({
	"lengthChange": false,
	"processing":true,
	"serverSide":true,		
	"bFilter": false,		
	'serverMethod': 'post',		
	"order":[],
	"ajax":{
		url:"order_action.php",
		type:"POST",
		data:{action:'listOrder'},
		dataType:"json"
	},
	"columnDefs":[
		{
			"targets":[0, 4, 5],
			"orderable":false,
		},
	],
	"pageLength": 10
});	

we will check for action listOrder and call method listOrder() from class Order.php

$order = new Order($db);

if(!empty($_POST['action']) && $_POST['action'] == 'listOrder') {
	$order->listOrder();
}

We will implement

public function listOrder(){		
		
	$sqlQuery = "SELECT orders.order_id, orders.order_date, customer.name
		FROM ".$this->orderTable." AS orders 
		LEFT JOIN ".$this->customerTable." AS customer ON customer.id = orders.userid ";			
		
	if(!empty($_POST["search"]["value"])){
		$sqlQuery .= ' WHERE (orders.order_id LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= ' OR orders.order_date LIKE "%'.$_POST["search"]["value"].'%" ';	
	}
	
	if(!empty($_POST["order"])){
		$sqlQuery .= 'GROUP BY orders.order_id ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'GROUP BY orders.order_id ORDER BY orders.order_date DESC ';
	}	
	
	$stmt = $this->conn->prepare($sqlQuery);
	$stmt->execute();
	$result = $stmt->get_result();	
	
	if($_POST["length"] != -1){
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}	
	
	$stmtTotal = $this->conn->prepare($sqlQuery);
	$stmtTotal->execute();
	$allResult = $stmtTotal->get_result();
	$allRecords = $allResult->num_rows;
	
	$displayRecords = $result->num_rows;
	$records = array();	
	$count = 1;
	while ($order = $result->fetch_assoc()) { 				
		$rows = array();			
		$rows[] = $count;			
		$rows[] = $order['order_id'];	
		$rows[] = $order['order_date'];	
		$rows[] = $order['name'];
		$rows[] = '<button type="button" name="view" id="'.$order["order_id"].'" class="btn btn-success btn-xs view"><span class="glyphicon glyphicon-file" title="View">View</span></button>';			
		$rows[] = '<button type="button" name="delete" id="'.$order["order_id"].'" class="btn btn-danger btn-xs delete" ><span class="glyphicon glyphicon-remove" title="Delete">Delete</span></button>';
		$records[] = $rows;
		$count++;
	}
	
	$output = array(
		"draw"	=>	intval($_POST["draw"]),			
		"iTotalRecords"	=> 	$displayRecords,
		"iTotalDisplayRecords"	=>  $allRecords,
		"data"	=> 	$records
	);
	
	echo json_encode($output);
}	

Step5: List Food Items – Front End

Now we will implement functionality to list food items on front end. We will call method itemsList() from class Food.php and loop through food items to list them.

<div class='row'>
	<?php 
	$result = $food->itemsList();
	$count=0;
	while ($item = $result->fetch_assoc()) { 
	if ($count == 0) {
		echo "<div class='row'>";
	}
	?>	
		<div class="col-md-3">
			<form method="post" action="cart.php?action=add&id=<?php echo $item["id"]; ?>">
				<div class="mypanel" align="center";>
					<img src="images/<?php echo $item["images"]; ?>" class="item-img" title="<?php echo $item["description"]; ?>">
					<h4 class="item-name"><?php echo $item["name"]; ?></h4>							
					<div class="item-price">$<?php echo $item["price"]; ?>/-</div>			
					<div class="row">
						<span class="col-md-1 text-info">Qty:</span> 
						<span class="col-md-4"><input type="number" min="1" max="25" name="quantity" class="form-control" value="1" style="width: 60px;"> </span>
						<span class="col-md-6"><input type="submit" name="add" class="btn btn-success" value="Add To Cart"></span>
					</div>
					
					<input type="hidden" name="item_name" value="<?php echo $item["name"]; ?>">
					<input type="hidden" name="item_price" value="<?php echo $item["price"]; ?>">
					<input type="hidden" name="item_id" value="<?php echo $item["id"]; ?>">		
				</div>
			</form>    
		</div>

	<?php 
	$count++;
	if($count==4)
	{
	  echo "</div>";
	  $count=0;
	}
	} 
	?>
</div>

We will implement method itemsList() in class Food.php and result.

public function itemsList(){		
	$stmt = $this->conn->prepare("SELECT id, name, price, description, images, status 
	FROM ".$this->foodItemsTable);				
	$stmt->execute();			
	$result = $stmt->get_result();		
	return $result;	
}

Step6: Manage Cart – Front End

We will create cart.php file and implement cart functionality to display cart items.

<div class='row'>		
<?php
if(!empty($_SESSION["cart"])){
?>      
	<h3>Your Cart</h3>    
	<table class="table table-striped">
	 <thead class="thead-dark">
	<tr>
	<th width="40%">Food Name</th>
	<th width="10%">Quantity</th>
	<th width="20%">Price Details</th>
	<th width="15%">Order Total</th>
	<th width="5%">Action</th>
	</tr>
	</thead>
	<?php
	$total = 0;
	foreach($_SESSION["cart"] as $keys => $values){
	?>
		<tr>
		<td><?php echo $values["item_name"]; ?></td>
		<td><?php echo $values["item_quantity"] ?></td>
		<td>$ <?php echo $values["item_price"]; ?></td>
		<td>$ <?php echo number_format($values["item_quantity"] * $values["item_price"], 2); ?></td>
		<td><a href="cart.php?action=delete&id=<?php echo $values["food_id"]; ?>"><span class="text-danger">Remove</span></a></td>
		</tr>
		<?php 
		$total = $total + ($values["item_quantity"] * $values["item_price"]);
	}
	?>
	<tr>
	<td colspan="3" align="right">Total</td>
	<td align="right">$ <?php echo number_format($total, 2); ?></td>
	<td></td>
	</tr>
	</table>
	<?php
	echo '<a href="cart.php?action=empty"><button class="btn btn-danger"><span class="glyphicon glyphicon-trash"></span> Empty Cart</button></a> <a href="index.php"><button class="btn btn-warning">Add more items</button></a> <a href="checkout.php"><button class="btn btn-success pull-right"><span class="glyphicon glyphicon-share-alt"></span> Check Out</button></a>';
	?>
<?php
} elseif(empty($_SESSION["cart"])){
?>
	<div class="container">
	<div class="jumbotron">
	<h3>Your cart is empty. Enjoy <a href="index.php">food list</a> here.</h3>        
	</div>      
	</div>    
<?php
}
?>		
</div>	

we will implement to manage cart.

if(isset($_POST["add"])){
	if(isset($_SESSION["cart"])){
		$item_array_id = array_column($_SESSION["cart"], "food_id");
		if(!in_array($_GET["id"], $item_array_id)){
			$count = count($_SESSION["cart"]);
			$item_array = array(
				'food_id' => $_GET["id"],
				'item_name' => $_POST["item_name"],
				'item_price' => $_POST["item_price"],
				'item_id' => $_POST["item_id"],
				'item_quantity' => $_POST["quantity"]
			);
			$_SESSION["cart"][$count] = $item_array;
			echo '<script>window.location="cart.php"</script>';
		} else {					
			echo '<script>window.location="cart.php"</script>';
		}
	} else {
		$item_array = array(
			'food_id' => $_GET["id"],
			'item_name' => $_POST["item_name"],
			'item_price' => $_POST["item_price"],
			'item_id' => $_POST["item_id"],
			'item_quantity' => $_POST["quantity"]
		);
		$_SESSION["cart"][0] = $item_array;
	}
}

if(isset($_GET["action"])){
	if($_GET["action"] == "delete"){
		foreach($_SESSION["cart"] as $keys => $values){
			if($values["food_id"] == $_GET["id"]){
				unset($_SESSION["cart"][$keys]);						
				echo '<script>window.location="cart.php"</script>';
			}
		}
	}
}

if(isset($_GET["action"])){
	if($_GET["action"] == "empty"){
		foreach($_SESSION["cart"] as $keys => $values){
			unset($_SESSION["cart"]);					
			echo '<script>window.location="cart.php"</script>';
		}
	}
}

Step7: Checkout Order – Front End

We will create a file checkout.php and implement checkout functionality.

<?php
$orderTotal = 0;
foreach($_SESSION["cart"] as $keys => $values){
	$total = ($values["item_quantity"] * $values["item_price"]);
	$orderTotal = $orderTotal + $total;
}
?>
<div class='row'>
	<div class="col-md-6">
		<h3>Delivery Address</h3>
		<?php 
		$addressResult = $customer->getAddress();
		$count=0;
		while ($address = $addressResult->fetch_assoc()) { 
		?>
		<p><?php echo $address["address"]; ?></p>
		<p><strong>Phone</strong>:<?php echo $address["phone"]; ?></p>
		<p><strong>Email</strong>:<?php echo $address["email"]; ?></p>
		<?php
		}
		?>				
	</div>
	<?php 
	$randNumber1 = rand(100000,999999); 
	$randNumber2 = rand(100000,999999); 
	$randNumber3 = rand(100000,999999);
	$orderNumber = $randNumber1.$randNumber2.$randNumber3;
	?>
	<div class="col-md-6">
		<h3>Order Summery</h3>
		<p><strong>Items</strong>: $<?php echo $orderTotal; ?></p>
		<p><strong>Delivery</strong>: $0</p>
		<p><strong>Total</strong>: $<?php echo $orderTotal; ?></p>
		<p><strong>Order Total</strong>: $<?php echo $orderTotal; ?></p>
		<p><a href="process_order.php?order=<?php echo $orderNumber;?>"><button class="btn btn-warning">Place Order</button></a></p>
	</div>
</div>

Demo Download