Welcome to a quick tutorial on how to create a simple reservation system with PHP and MySQL. So you are offering a service and want to open up for online booking? Or maybe you have some rooms available for reservations?
A bare basic reservation system only has a few key components:
- A database table to store the reservations.
- A PHP library to process the reservations.
- The reservation page itself.
But just how is it done exactly? Let us walk an example in this guide – Read on!
TABLE OF CONTENTS
DOWNLOAD & NOTES
Here is the download link to the example code, so you don’t have to copy-paste everything.
EXAMPLE CODE DOWNLOAD
Just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
SORRY FOR THE ADS...
But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.
Buy Me A Coffee Code Boxx eBooks
PHP RESERVATION SYSTEM
All right, let us now get into more detail about building a reservation system with PHP and MYSQL.
TUTORIAL VIDEO
STEP 1) RESERVATIONS DATABASE TABLE
CREATE TABLE `reservations` (
`res_id` bigint(20) NOT NULL,
`res_date` date,
`res_slot` varchar(32) DEFAULT NULL,
`res_name` varchar(255) NOT NULL,
`res_email` varchar(255) NOT NULL,
`res_tel` varchar(60) NOT NULL,
`res_notes` text DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `reservations`
ADD PRIMARY KEY (`res_id`),
ADD KEY `res_date` (`res_date`),
ADD KEY `res_slot` (`res_slot`),
ADD KEY `res_name` (`res_name`),
ADD KEY `res_email` (`res_email`),
ADD KEY `res_tel` (`res_tel`);
ALTER TABLE `reservations`
MODIFY `res_id` bigint(20) NOT NULL AUTO_INCREMENT;
Field | Description |
res_id |
Reservation ID. Primary key, auto-increment. |
res_date |
Self-explanatory, the reservation date. |
res_slot |
For time slot booking, this is an open text field that is up to you to decide – Offer hourly slots, AM/PM, or don’t use this at all (for whole day booking). |
res_name |
Name of the customer. |
res_email |
Email of the customer. |
res_tel |
Telephone number of the customer. |
res_notes |
Reservation notes, if any. |
That should cover all the basics, feel free to add more fields as your project requires.
STEP 2) PHP RESERVATION CLASS
<?php
class Reservation {
// (A) CONSTRUCTOR - CONNECT TO DATABASE
private $pdo; // pdo object
private $stmt; // sql statement
public $error; // error message
function __construct() {
$this->pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_NAMED
]);
}
// (B) DESTRUCTOR - CLOSE DATABASE CONNECTION
function __destruct() {
$this->pdo = null;
$this->stmt = null;
}
// (C) HELPER - EXECUTE SQL QUERY
function query ($sql, $data=null) : void {
$this->stmt = $this->pdo->prepare($sql);
$this->stmt->execute($data);
}
// (D) SAVE RESERVATION
function save ($date, $slot, $name, $email, $tel, $notes="") {
// (D1) CHECKS & RESTRICTIONS
// @TODO - ADD YOUR OWN RULES & REGULATIONS HERE
// MAX # OF RESERVATIONS ALLOWED?
// USER CAN ONLY BOOK X DAYS IN ADVANCE?
// USER CAN ONLY BOOK A MAX OF X SLOTS WITHIN Y DAYS?
// (D2) DATABASE ENTRY
$this->query(
"INSERT INTO `reservations` (`res_date`, `res_slot`, `res_name`, `res_email`, `res_tel`, `res_notes`) VALUES (?,?,?,?,?,?)",
[$date, $slot, $name, $email, $tel, $notes]
);
// (D3) EMAIL
// @TODO - REMOVE IF YOU WANT TO MANUALLY CALL TO CONFIRM OR SOMETHING
// OR EMAIL THIS TO A MANAGER OR SOMETHING
$subject = "Reservation Received";
$message = "Thank you, we have received your request and will process it shortly.";
@mail($email, $subject, $message);
return true;
}
// (E) GET RESERVATIONS FOR THE DAY
function getDay ($day="") {
// (E1) DEFAULT TO TODAY
if ($day=="") { $day = date("Y-m-d"); }
// (E2) GET ENTRIES
$this->query("SELECT * FROM `reservations` WHERE `res_date`=?", [$day]);
return $this->stmt->fetchAll();
}
}
// (F) DATABASE SETTINGS - CHANGE THESE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8mb4");
define("DB_USER", "root");
define("DB_PASSWORD", "");
// (G) NEW RESERVATION OBJECT
$_RSV = new Reservation();
Yes, this library looks massive at first, but keep calm and look carefully.
- (A, B, G) When
$_RSV = new Reservation()
is created, the constructor will automatically connect to the database. The destructor closes the connection. - (C)
query()
A helper function to run an SQL query. - (D & E) There are only 2 functions here!
save()
This will be used to save the reservation when the user submits the reservation/booking form.get()
Gets all reservations for a specified day, an example of what you might want to use in your own admin panel.
- (F) Remember to change the database settings to your own.
That should cover all the raw essentials of a reservation system.
STEP 3) DUMMY RESERVATIONS PAGE
<?php
// (A) PROCESS RESERVATION
if (isset($_POST["date"])) {
require "2-reserve.php";
if ($_RSV->save(
$_POST["date"], $_POST["slot"], $_POST["name"],
$_POST["email"], $_POST["tel"], $_POST["notes"])) {
echo "<div class='note'>Reservation saved.</div>";
} else { echo "<div class='note'>".$_RSV->error."</div>"; }
}
?>
<!-- (B) RESERVATION FORM -->
<form id="resForm" method="post" target="_self">
<label>Name</label>
<input type="text" required name="name" value="Jon Doe">
<label>Email</label>
<input type="email" required name="email" value="jon@doe.com">
<label>Telephone Number</label>
<input type="text" required name="tel" value="123456789">
<label>Notes (if any)</label>
<input type="text" name="notes" value="Testing">
<?php
// @TODO - MINIMUM DATE (TODAY)
// $mindate = date("Y-m-d", strtotime("+2 days"));
$mindate = date("Y-m-d");
?>
<label>Reservation Date</label>
<input type="date" required name="date" value="<?=date("Y-m-d")?>">
<label>Reservation Slot</label>
<select name="slot">
<option value="AM">AM</option>
<option value="PM">PM</option>
</select>
<input type="submit" value="Submit">
</form>
No need to panic – This looks confusing but is actually very straightforward.
- (B) This should be self-explanatory, the HTML reservation form itself.
- (A) When the form is submitted, we use the library to process and save the reservation.
EXTRA) RESERVATIONS REPORT
// (A) GET ALL RESERVATIONS
require "2-reserve.php";
$all = $_RSV->getDay();
// (B) OUTPUT CSV
header("Content-Type: text/csv");
header("Content-Disposition: attachment;filename=reservations.csv");
if (count($all)==0) { echo "No reservations"; }
else {
// (B1) FIRST ROW - HEADERS
foreach ($all[0] as $k=>$v) { echo "$k,"; }
echo "\r\n";
// (B2) RESERVATION DETAILS
foreach ($all as $r) {
foreach ($r as $k=>$v) { echo "$v,"; }
echo "\r\n";
}
}
Everyone is going to have a different system and starting point, but here is another small script that will demonstrate how the library can be used to generate reports.
EXTRAS
That’s all for the project, and here are a few small extras that may be useful to you.
ADDING MORE FIELDS
- Change the database table, add more fields.
- Update
function save()
to also include the extra fields. - Lastly, update the HTML form.
I DON’T NEED THE TIME SLOT
Just leave it as NULL
, or remove it totally.
DATE RANGE BOOKING
This is kind of tricky, as everyone will have different requirements. For example:
- Some may have AM/PM timeslots. Booking an overnight stay may mean “Day 1 PM plus DAY 2 AM”, and not “2 full days”. So yep, that is 2 timeslots.
- Others may only offer “full-day bookings”. In this case, feel free to change the database to “date start and date end” instead of “date and time slot”.
- A few others may get extremely complicated with “pay by the hour”. In this case, it is best to store “time start” and “time end” instead.
There is no way to create a “one-size-fits-all” system here – This is your homework.
LINKS & REFERENCES
- User Registration Form In PHP MYSQL (With Email Verification) – Code Boxx
- Simple AJAX User Login Page (With PHP MySQL) – Code Boxx
- Simple PHP Admin Panel – Code Boxx
- Mail Not Sending Out? – Code Boxx
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!
it’s not working. I can fill in the form but that’s it. Nothing happens.
Any idea?
https://code-boxx.com/faq/#notwork
Thank you for the code but can you also provide tutorial for multi restaurant reservation ?
“Simple fix” – Just add a “choose restaurant” dropdown by yourself. Otherwise:
https://code-boxx.com/faq/#help “Requests for new features and tutorials may be considered, but will not be immediately answered”
Thankyou for this fab reservation form.
I was wondering if anyone could help I am trying to add the a time field like so: `res_timey` time is added to the table and the altertable.,
I am receiving a Syntax error or access violation when I add new field to the table and change the table and send function accordingly.
Has anyone added to the table? Could they detail how they went about doing this?
hi there, ty for the free code much appreciated.
i am trying to put a max reservation in a day can you help me pls.
Just do a
SELECT COUNT(*) FROM `RESERVATIONS` WHERE `RES_DATE`="YYYY-MM-DD"
? If you don’t even know that is, I will highly suggest you revisit the basics… Or don’t cheap out on hiring a web developer.https://code-boxx.com/faq/#help
Good Morning,
Many thank for the free code. I called around and got an average estimate of $700 just for this code.
My question is
How can I add a drop down list for user to select from multiple locations and also include that data on the ticket?
Very easy, don’t cheap out and pay freelancers to do it – There’s a good reason why they quoted you that price.
FYI – Here is how much a web developer is supposed to be paid. https://www.indeed.com/career/web-developer/salaries
https://code-boxx.com/faq/#help