In our previous tutorial, we have explained how to develop Visitor Management System with PHP and MySQL. In this tutorial, we will develop Restaurant Management System with PHP and MySQL.
Restaurant Management System are widely used to manage food category, food items, tables, orders, tax and billing. The Restaurant Management System allows waiter or cashier to manage order with items and finally create bill instead of handling everything manually.
So if you’re a web developer or programmer and looking for solution to develop Restaurant Management System, then you’re here at the right place. In this tutorial you learn how to develop your own restaurant system with PHP and MySQL.
Also, read:
Here we will develop an example of online Restaurant Management System and cover following.
The Administrator will do the following:
- Manage Food Category.
- Manage Food Items.
- Manage Tables.
- Manage Orders.
- Manage Taxes.
- Manage Billing.
The Cashier will do the following:
- Manage Orders.
- Manage Billing.
The Waiter will do the following:
- Manage Orders.
So let’s implement Restaurant Management System . The major files are:
- index.php
- category.php
- items.php
- tables.php
- orders.php
- taxes.php
- User.php: User class to hold methods related to user.
- Category.php: Category class to hold methods related to food category.
- Item.php: Item class to hold methods related to food items.
- Tables.php: Tables class to hold methods related to manage tables.
- Order.php: Order class to hold methods related to manage orders.
Step1: Create MySQL Database Table
Firs we will create restaurant_user
table to store user information with login details to access system.
CREATE TABLE `restaurant_user` ( `id` int(11) UNSIGNED NOT NULL, `first_name` varchar(255) DEFAULT NULL, `last_name` varchar(255) DEFAULT NULL, `gender` enum('Male','Female') NOT NULL, `email` varchar(255) DEFAULT NULL, `password` varchar(64) NOT NULL, `mobile` varchar(12) NOT NULL, `address` text NOT NULL, `created` datetime NOT NULL DEFAULT current_timestamp(), `role` enum('admin','waiter','cashier') DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
we will create table restaurant_category
store food categories.
CREATE TABLE `restaurant_category` ( `id` int(11) NOT NULL, `name` varchar(250) COLLATE utf8_unicode_ci NOT NULL, `status` enum('Enable','Disable') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Enable' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
we will create table restaurant_items
to store food items details.
CREATE TABLE `restaurant_items` ( `id` int(11) NOT NULL, `name` varchar(250) COLLATE utf8_unicode_ci NOT NULL, `price` decimal(10,2) NOT NULL, `category_id` int(11) NOT NULL, `status` enum('Enable','Disable') COLLATE utf8_unicode_ci NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
we will create table restaurant_table
to store table details.
CREATE TABLE `restaurant_table` ( `id` int(11) NOT NULL, `name` varchar(250) COLLATE utf8_unicode_ci NOT NULL, `capacity` int(3) NOT NULL, `status` enum('Enable','Disable') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Enable' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
we will create table restaurant_tax
to store taxes details.
CREATE TABLE `restaurant_tax` ( `id` int(11) NOT NULL, `tax_name` varchar(250) COLLATE utf8_unicode_ci NOT NULL, `percentage` decimal(4,2) NOT NULL, `status` enum('Enable','Disable') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Enable' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
we will create table restaurant_order
to store order details.
CREATE TABLE `restaurant_order` ( `id` int(11) NOT NULL, `table_id` varchar(250) COLLATE utf8_unicode_ci NOT NULL, `gross_amount` decimal(12,2) NOT NULL, `tax_amount` decimal(12,2) NOT NULL, `net_amount` decimal(12,2) NOT NULL, `created` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `created_by` enum('admin','waiter','cashier') COLLATE utf8_unicode_ci NOT NULL, `status` enum('In Process','Completed') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'In Process' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
and we will create table restaurant_order_item
to store order items details.
CREATE TABLE `restaurant_order_item` ( `id` int(11) NOT NULL, `order_id` int(11) NOT NULL, `category_id` int(11) NOT NULL, `item_id` int(11) NOT NULL, `quantity` int(4) NOT NULL, `rate` decimal(12,2) NOT NULL, `amount` decimal(12,2) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Step2: Manage Food Category
We will create HTML in category.php
file to list food categories. We will also create HTML to add, edit and delete categories.
<div> <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="addCategory" class="btn btn-info" title="Add Category"><span class="glyphicon glyphicon-plus"></span></button> </div> </div> </div> <table id="categoryListing" class="table table-bordered table-striped"> <thead> <tr> <th>Id</th> <th>Category Name</th> <th>Status</th> <th></th> <th></th> </tr> </thead> </table> </div> <div id="categoryModal" class="modal fade"> <div class="modal-dialog"> <form method="post" id="categoryForm"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title"><i class="fa fa-plus"></i> Edit Category</h4> </div> <div class="modal-body"> <div class="form-group"> <div class="row"> <label class="col-md-4 text-right">Category Name <span class="text-danger">*</span></label> <div class="col-md-8"> <input type="text" name="categoryName" id="categoryName" autocomplete="off" class="form-control" required /> </div> </div> </div> <div class="form-group"> <div class="row"> <label class="col-md-4 text-right">Status <span class="text-danger">*</span></label> <div class="col-md-8"> <select name="status" id="status" class="form-control"> <option value="Enable">Enable</option> <option value="Disable">Disable</option> </select> </div> </div> </div> </div> <div class="modal-footer"> <input type="hidden" name="id" id="id" /> <input type="hidden" name="action" id="action" value="" /> <input type="submit" name="save" id="save" class="btn btn-info" value="Save" /> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </form> </div> </div>
we will make ajax request to category_action.php
with action listCategory
to load categories.
var categoryRecords = $('#categoryListing').DataTable({ "lengthChange": false, "processing":true, "serverSide":true, "bFilter": true, 'serverMethod': 'post', "order":[], "ajax":{ url:"category_action.php", type:"POST", data:{action:'listCategory'}, dataType:"json" }, "columnDefs":[ { "targets":[0, 3, 4], "orderable":false, }, ], "pageLength": 10 });
we will check for action listCategory
in category_action.php
and call method listCategory()
from class Category.php
.
if(!empty($_POST['action']) && $_POST['action'] == 'listCategory') { $category->listCategory(); }
we will implement method listCategory()
in class Category.php
to list categories.
public function listCategory(){ $sqlQuery = " SELECT id, name, status FROM ".$this->categoryTable." "; if(!empty($_POST["order"])){ $sqlQuery .= ' ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' '; } else { $sqlQuery .= ' ORDER BY id ASC '; } 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(); while ($category = $result->fetch_assoc()) { $rows = array(); $rows[] = $category['id']; $rows[] = $category['name']; $rows[] = $category['status']; $rows[] = '<button type="button" name="update" id="'.$category["id"].'" class="btn btn-warning btn-xs update"><span class="glyphicon glyphicon-edit" title="Edit"></span></button>'; $rows[] = '<button type="button" name="delete" id="'.$category["id"].'" class="btn btn-danger btn-xs delete" ><span class="glyphicon glyphicon-remove" title="Delete"></span></button>'; $records[] = $rows; } $output = array( "draw" => intval($_POST["draw"]), "iTotalRecords" => $displayRecords, "iTotalDisplayRecords" => $allRecords, "data" => $records ); echo json_encode($output); }
We will also implement functionality to add new category, edit category and delete category.
Step3: Manage Food Items
We will create HTML in items.php
to add, edit, delete and list food items.
<div> <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="addItems" class="btn btn-info" title="Add Food Items"><span class="glyphicon glyphicon-plus"></span></button> </div> </div> </div> <table id="itemsListing" class="table table-bordered table-striped"> <thead> <tr> <th>Id</th> <th>Item Name</th> <th>Price</th> <th>Category</th> <th>Status</th> <th></th> <th></th> </tr> </thead> </table> </div> <div id="itemModal" class="modal fade"> <div class="modal-dialog"> <form method="post" id="itemForm"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title"><i class="fa fa-plus"></i> Edit Items</h4> </div> <div class="modal-body"> <div class="form-group"> <div class="row"> <label class="col-md-4 text-right">Item Name <span class="text-danger">*</span></label> <div class="col-md-8"> <input type="text" name="itemName" id="itemName" autocomplete="off" class="form-control" required /> </div> </div> </div> <div class="form-group"> <div class="row"> <label class="col-md-4 text-right">Price <span class="text-danger">*</span></label> <div class="col-md-8"> <input type="text" name="price" id="price" autocomplete="off" class="form-control" required /> </div> </div> </div> <div class="form-group"> <div class="row"> <label class="col-md-4 text-right">Item Category <span class="text-danger">*</span></label> <div class="col-md-8"> <select name="itemCategory" id="itemCategory" class="form-control"> <?php $categoryResult = $item->getItemCategory(); while ($category = $categoryResult->fetch_assoc()) { ?> <option value="<?php echo $category['id']; ?>"><?php echo $category['name']; ?></option> <?php } ?> </select> </div> </div> </div> <div class="form-group"> <div class="row"> <label class="col-md-4 text-right">Status <span class="text-danger">*</span></label> <div class="col-md-8"> <select name="status" id="status" class="form-control"> <option value="Enable">Enable</option> <option value="Disable">Disable</option> </select> </div> </div> </div> </div> <div class="modal-footer"> <input type="hidden" name="id" id="id" /> <input type="hidden" name="action" id="action" value="" /> <input type="submit" name="save" id="save" class="btn btn-info" value="Save" /> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </form> </div> </div>
we will make ajax request to items_action.php
with action listItems
to load items in datatables.
var itemRecords = $('#itemsListing').DataTable({ "lengthChange": false, "processing":true, "serverSide":true, "bFilter": true, 'serverMethod': 'post', "order":[], "ajax":{ url:"items_action.php", type:"POST", data:{action:'listItems'}, dataType:"json" }, "columnDefs":[ { "targets":[0, 5, 6], "orderable":false, }, ], "pageLength": 10 });
we will check for action listItems
and call method listItems()
from class Items.php
to load items list.
if(!empty($_POST['action']) && $_POST['action'] == 'listItems') { $item->listItems(); }
we will implement method listItems()
in class Items.php
to get items record and return as JSON data to load in datatables.
public function listItems(){ $sqlQuery = " SELECT item.id, item.name AS item_name, item.price, item.category_id, item.status, category.name AS category_name FROM ".$this->itemTable." item LEFT JOIN ".$this->categoryTable." category ON item.category_id = category.id "; if(!empty($_POST["order"])){ $sqlQuery .= ' ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' '; } else { $sqlQuery .= ' ORDER BY item.id ASC '; } 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(); while ($items = $result->fetch_assoc()) { $rows = array(); $rows[] = $items['id']; $rows[] = $items['item_name']; $rows[] = "$".$items['price']; $rows[] = $items['category_name']; $rows[] = $items['status']; $rows[] = '<button type="button" name="update" id="'.$items["id"].'" class="btn btn-warning btn-xs update"><span class="glyphicon glyphicon-edit" title="Edit"></span></button>'; $rows[] = '<button type="button" name="delete" id="'.$items["id"].'" class="btn btn-danger btn-xs delete" ><span class="glyphicon glyphicon-remove" title="Delete"></span></button>'; $records[] = $rows; } $output = array( "draw" => intval($_POST["draw"]), "iTotalRecords" => $displayRecords, "iTotalDisplayRecords" => $allRecords, "data" => $records ); echo json_encode($output); }
we have also implemented items add, edit and delete functionality.
Step4: Manage Orders
In order.php
, we will create HTML to manage orders. We will implement to create new order, edit and delete order.
<div> <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"></span></button> </div> </div> </div> <table id="orderListing" class="table table-bordered table-striped"> <thead> <tr> <th>Order Id</th> <th>Table</th> <th>Gross Amount</th> <th>Tax Amount</th> <th>Net Amount</th> <th>Date Time</th> <th>Created By</th> <th>Status</th> <th></th> <th></th> </tr> </thead> </table> </div> <div id="orderModal" class="modal fade"> <div class="modal-dialog" style="width"> <form method="post" id="orderForm"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title"><i class="fa fa-plus"></i> Edit Order</h4> </div> <div class="modal-body"> <div class="form-group"> <div class="row"> <table class="table table-bordered table-hover"> <tr> <th width="10%">Table *</th> </tr> <tr> <td> <select name="tableName" id="tableName" class="form-control" required> <option value="">--Select--</option> <?php $tableResult = $order->getTable(); while ($table = $tableResult->fetch_assoc()) { ?> <option value="<?php echo $table['id']; ?>"><?php echo $table['name']; ?></option> <?php } ?> </select> </td> </tr> </table> <table class="table table-bordered table-hover" id="orderItem"> <tr> <th width="2%"><input id="checkAll" class="formcontrol" type="checkbox"></th> <th width="25%">Category</th> <th width="25%">Item</th> <th width="15%">Price</th> <th width="10%">Quantity</th> <th width="15%">Total</th> </tr> <tr> <td><input class="itemRow" type="checkbox"></td> <td> <select name="itemCategory[]" id="itemCategory_1" class="form-control"> <option value="">--Select--</option> <?php $categoryResult = $item->getItemCategory(); while ($category = $categoryResult->fetch_assoc()) { ?> <option value="<?php echo $category['id']; ?>"><?php echo $category['name']; ?></option> <?php } ?> </select> </td> <td> <select name="items[]" id="items_1" class="form-control"></select> </td> <td><input type="number" name="price[]" id="price_1" class="form-control price" autocomplete="off"></td> <td><input type="number" name="quantity[]" id="quantity_1" class="form-control quantity" autocomplete="off"></td> <td><input type="number" name="total[]" id="total_1" class="form-control total" autocomplete="off"></td> <input type="hidden" name="itemIds[]" id="itemIds_1" class="form-control" > </tr> </table> </div> <div class="row"> <button class="btn btn-danger delete" id="removeRows" type="button">- Delete</button> <button class="btn btn-success" id="addRows" type="button">+ Add More</button> </div> </div> <div class="row"> <div class="col-xs-12 col-sm-8 col-md-8 col-lg-8"> <div class="form-group"> <br><br><br><br><br><br><br><br><br><br> <label class="col-md-2">Status <span class="text-danger">*</span></label> <div class="col-md-9"> <select name="status" id="status" class="form-control" required> <option value="In Process">In Process</option> <option value="Completed">Completed</option> </select> </div> <br><br> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <input type="submit" name="save" id="save" class="btn btn-info" value="Save" /> </div> </div> <div class="col-xs-12 col-sm-4 col-md-4 col-lg-4"> <span class="form-inline"> <div class="form-group"> <label>Subtotal: </label> <div class="input-group"> <div class="input-group-addon currency">$</div> <input value="" type="text" class="form-control" name="subTotal" id="subTotal" placeholder="Subtotal"> </div> </div> <div class="form-group"> <label>CGST Rate: </label> <div class="input-group"> <input value="" type="text" class="form-control" name="taxRate1" id="taxRate1" placeholder="CGST Rate"> <div class="input-group-addon">%</div> </div> </div> <div class="form-group"> <label>SGST Rate: </label> <div class="input-group"> <input value="" type="text" class="form-control" name="taxRate2" id="taxRate2" placeholder="SGST Rate"> <div class="input-group-addon">%</div> </div> </div> <div class="form-group"> <label>Tax Amount: </label> <div class="input-group"> <div class="input-group-addon currency">$</div> <input value="" type="text" class="form-control" name="taxAmount" id="taxAmount" placeholder="Tax Amount"> </div> </div> <div class="form-group"> <label>Net Amount: </label> <div class="input-group"> <div class="input-group-addon currency">$</div> <input value="" type="text" class="form-control" name="totalAftertax" id="totalAftertax" placeholder="Total"> </div> </div> </span> </div> </div> </div> <div class="modal-footer"> <input type="hidden" name="id" id="id" /> <input type="hidden" name="action" id="action" value="" /> </div> </div> </form> </div> </div>
we will implement functionality to list order datatables. So we will initialize datatables and make ajax request to order_action.php
with action listOrder
.
var orderRecords = $('#orderListing').DataTable({ "lengthChange": false, "processing":true, "serverSide":true, "bFilter": true, 'serverMethod': 'post', "order":[], "ajax":{ url:"order_action.php", type:"POST", data:{action:'listOrder'}, dataType:"json" }, "columnDefs":[ { "targets":[0, 8, 9], "orderable":false, }, ], "pageLength": 10 });
we will check for action listOrder
and call method listOrder()
from class Order.php
to list orders.
if(!empty($_POST['action']) && $_POST['action'] == 'listOrder') { $order->listOrder(); }
and finally we will implement method listOrder()
in class Order.php
to get orders from database and list them.
public function listOrder(){ $sqlQuery = " SELECT orders.id, orders.gross_amount, orders.tax_amount, orders.net_amount, orders.created, orders.created_by, orders.status, tables.name AS table_name FROM ".$this->orderTable." orders LEFT JOIN ".$this->tableTable." tables ON orders.table_id = tables.id "; if(!empty($_POST["order"])){ $sqlQuery .= ' ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' '; } else { $sqlQuery .= ' ORDER BY orders.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(); while ($order = $result->fetch_assoc()) { $rows = array(); $rows[] = $order['id']; $rows[] = $order['table_name']; $rows[] = "$".$order['gross_amount']; $rows[] = "$".$order['tax_amount']; $rows[] = "$".$order['net_amount']; $rows[] = $order['created']; $rows[] = $order['created_by']; $rows[] = $order['status']; $rows[] = '<button type="button" name="update" id="'.$order["id"].'" class="btn btn-warning btn-xs update"><span class="glyphicon glyphicon-edit" title="Edit"></span></button>'; $rows[] = '<button type="button" name="delete" id="'.$order["id"].'" class="btn btn-danger btn-xs delete" ><span class="glyphicon glyphicon-remove" title="Delete"></span></button>'; $records[] = $rows; } $output = array( "draw" => intval($_POST["draw"]), "iTotalRecords" => $displayRecords, "iTotalDisplayRecords" => $allRecords, "data" => $records ); echo json_encode($output); }
we have also implemented orders create, edit and delete functionality.
You may also like:
- Follow and Unfollow System with PHP & MySQL
- GST Billing System with PHP & MySQL
- Student Attendance System with PHP & MySQL
- Like and Dislike System with Ajax, PHP & MySQL
- Build Star Rating System with jQuery, PHP & MySQL
- User Registration and Login System with PHP & MySQL
- Build Contact Form with PHP and Ajax
- To-do List Application with Ajax, PHP & MySQL
- Build Event Calendar with jQuery , PHP & MySQL
You can view the live demo from the Demo link and can download the source from the Download link below.
Demo Download
sorry, search and tabulation datatable not working
checking this and update you, thanks!