Simple Bus Ticket Booking System In PHP (Free Download)

Welcome to a tutorial on how to create a simple bus ticket booking system in PHP and MySQL. Working for a client who is going to run a fleet of buses? Or just doing this as an old-school assignment? Well, here’s a simple booking system that will kickstart your project. 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

Source code on GitHub Gist

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 MYSQL BUS TICKET BOOKING

All right, let us now get into more details on how the PHP MYSQL bus ticket booking system works.

 

 

PART 1) THE DATABASE

1A) SEATS TABLE

1-database.sql
-- (A) AVAILABLE SEATS
CREATE TABLE `seats` (
  `bus_id` varchar(16) NOT NULL,
  `seat_id` varchar(16) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `seats`
  ADD PRIMARY KEY (`seat_id`,`bus_id`);

INSERT INTO `seats` (`bus_id`, `seat_id`) VALUES
('BUS-A', 'A1'),
('BUS-A', 'A2'),
('BUS-A', 'A3'),
('BUS-A', 'A4'),
('BUS-A', 'B1'),
('BUS-A', 'B2'),
('BUS-A', 'B3'),
('BUS-A', 'B4'),
('BUS-A', 'C1'),
('BUS-A', 'C2'),
('BUS-A', 'C3'),
('BUS-A', 'C4');

This table should be self-explanatory, to store the seats available on the buses.

  • bus_id Partial primary key, vehicle registration number.
  • seat_id Partial primary key.

Well, feel free to add more fields as required – Window seat, smoking allowed, or even invent your own “grid system” to properly store the seat layout.

 

 

1B) TRIPS TABLE

1-database.sql
-- (B) TRIPS
CREATE TABLE `trips` (
  `trip_id` bigint(20) NOT NULL,
  `bus_id` varchar(16) NOT NULL,
  `trip_date` datetime NOT NULL,
  `trip_from` varchar(255) NOT NULL,
  `trip_to` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `trips`
  ADD PRIMARY KEY (`trip_id`),
  ADD KEY `bus_id` (`bus_id`),
  ADD KEY `trip_date` (`trip_date`);

ALTER TABLE `trips`
  MODIFY `trip_id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;

INSERT INTO `trips` (`trip_id`, `bus_id`, `trip_date`, `trip_from`, `trip_to`) VALUES
(1, 'BUS-A', '2077-06-05 00:00:00', 'Point A', 'Point B');
  • trip_id Primary key, auto-increment.
  • bus_id Foreign key.
  • trip_date When the trip takes place.
  • trip_from Board the bus here.
  • trip_to Destination.

 

 

1C) RESERVATIONS TABLE

1-database.sql
-- (C) RESERVATIONS
CREATE TABLE `reservations` (
  `trip_id` bigint(20) NOT NULL,
  `user_id` bigint(20) NOT NULL,
  `email` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `reservations`
  ADD PRIMARY KEY (`trip_id`, `user_id`),
  ADD KEY `email` (`email`);
  • trip_id Partial primary and foreign key.
  • user_id Partial primary and foreign key.
  • email Customer’s email.
  • name Customer’s name.

Some of you sharp code ninjas should have question marks over why we are storing the email and name, when we can retrieve the data from the user table. This is not redundant, customers may be booking for someone else or on behalf of their company.

P.S. Add more fields as necessary again.

 

1D) RESERVED SEATS

1-database.sql
-- (D) RESERVED SEATS
CREATE TABLE `reserve_seats` (
  `trip_id` bigint(20) NOT NULL,
  `user_id` bigint(20) NOT NULL,
  `seat_id` varchar(16) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
ALTER TABLE `reserve_seats`
  ADD PRIMARY KEY (`trip_id`, `user_id`, `seat_id`);

A “sub table” for reservations, to store which seats are selected. trip_id user_id seat_id are all primary and foreign keys.

 

 

PART 2) PHP LIBRARY

2-bus-lib.php
<?php
class Bus {
  // (A) CONSTRUCTOR - CONNECT TO DATABASE
  private $pdo = null;
  private $stmt = null;
  public $error = null;
  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_ASSOC
    ]);
  }

  // (B) DESTRUCTOR - CLOSE DATABASE CONNECTION
  function __destruct () {
    if ($this->stmt !== null) { $this->stmt = null; }
    if ($this->pdo !== null) { $this->pdo = null; }
  }

  // (C) HELPER FUNCTION - RUN SQL QUERY
  function query ($sql, $data=null) : void {
    $this->stmt = $this->pdo->prepare($sql);
    $this->stmt->execute($data);
  }

  // (D) ADD/EDIT TRIP
  function trip ($bus, $date, $from, $to, $tid=null) {
    // (D1) SQL & DATA
    if ($tid==null) {
      $sql = "INSERT INTO `trips` 
        (`bus_id`, `trip_date`, `trip_from`, `trip_to`)
        VALUES (?,?,?,?)";
      $data = [$bus, $date, $from, $to];
    } else {
      $sql = "UPDATE `trips` SET
        `bus_id`=?, `trip_date`=?, `trip_from`=?, `trip_to`=?
        WHERE `trip_id`=?";
      $data = [$bus, $date, $from, $to, $tid];
    }

    // (D2) RESULTS
    $this->query($sql, $data);
    return true;
  }

  // (E) GET GIVEN TRIP
  function get ($tid) {
    // (E1) TRIP DATA
    $this->query("SELECT * FROM `trips` WHERE `trip_id`=?", [$tid]);
    $trip = $this->stmt->fetch();
    if (!is_array($trip)) { return false; }

    // (E2) SEATS
    $this->query(
      "SELECT s.`seat_id`, r.`user_id`
       FROM `seats` s
       LEFT JOIN `trips` t USING (`bus_id`)
       LEFT JOIN `reserve_seats` r USING(`seat_id`)
       WHERE t.`trip_id`=?
       ORDER BY s.`seat_id`",
      [$tid]
    );
    $trip["seats"] = $this->stmt->fetchAll();
    return $trip;
  }

  // (F) SAVE RESERVATION
  function reserve ($tid, $uid, $email, $name, $seats) {
    // (F1) RESERVATIONS TABLE
    $this->query(
      "INSERT INTO `reservations` (`trip_id`, `user_id`, `email`, `name`) VALUES (?,?,?,?)",
      [$tid, $uid, $email, $name]
    );

    // (F2) SELECTED SEATS
    $sql = "INSERT INTO `reserve_seats` (`trip_id`, `user_id`, `seat_id`) VALUES ";
    foreach ($seats as $seat) {
      $sql .= "(?,?,?),";
      $data[] = $tid;
      $data[] = $uid;
      $data[] = $seat;
    }
    $sql = substr($sql, 0, -1);
    $this->query($sql, $data);
    return true;
  }
}

// (G) DATABASE SETTINGS - CHANGE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8mb4");
define("DB_USER", "root");
define("DB_PASSWORD", "");

// (H) NEW BUS BOOKING OBJECT
$_BUS = new Bus();

The library may look massive at first, but keep and look closely.

  • (A, B, H) When $_BUS = new Bus() is created, the constructor connects to the database. The destructor closes the connection.
  • (C) query() A simple helper function to run an SQL statement.
  • (D To F) The “actual” booking functions.
    • trip() Add or edit a trip.
    • get() Get the specified trip.
    • reserve() Save a reservation.
  • (G) Self-explanatory. Change the settings to your own.

 

 

PART 3) TICKET BOOKING PAGE

3A) THE HTML

3a-reservation.php
<?php
// (A) FIXED FOR THIS DEMO
$tripid = 1;
$userid = 999;

// (B) GET TRIP
require "2-bus-lib.php";
$trip = $_BUS->get($tripid);
?>

<!-- (C) TRIP INFO -->
<div class="info">
  <div class="iLeft">Date</div>
  <div class="iRight"><?=$trip["trip_date"]?></div>
</div>
<div class="info">
  <div class="iLeft">From</div>
  <div class="iRight"><?=$trip["trip_from"]?></div>
</div>
<div class="info">
  <div class="iLeft">To</div>
  <div class="iRight"><?=$trip["trip_to"]?></div>
</div>
 
<!-- (D) DRAW SEATS LAYOUT -->
<div id="layout"><?php foreach ($trip["seats"] as $s) {
  $taken = is_numeric($s["user_id"]);
  printf("<div class='seat%s'%s>%s</div>",
    $taken ? " taken" : "",
    $taken ? "" : " onclick='reserve.toggle(this)'",
    $s["seat_id"]
  );
} ?></div>
 
<!-- (E) LEGEND -->
<div class="legend">
  <div class="box"></div> Open
</div>
<div class="legend">
  <div class="box taken"></div> Taken
</div>
<div class="legend">
  <div class="box selected"></div> Your selected seats
</div>
 
<!-- (F) SAVE RESERVATION -->
<form id="form" method="post" action="4-save.php" onsubmit="return reserve.save();">
  <input type="hidden" name="tid" value="<?=$tripid?>">
  <input type="hidden" name="uid" value="<?=$userid?>">
  <label>Name</label>
  <input type="text" name="name" required value="Jon Doe">
  <label>Email</label>
  <input type="email" name="email" required value="jon@doe.com">
  <input type="submit" value="Reserve Seats">
</form>

Not going to explain the HTML page line-by-line, but a quick walkthrough:

  • (A & B) Load the PHP library, and get information on the trip. The trip id and user id are fixed for this demo.
  • (C) Information on the trip itself.
  • (D) Seats layout and select a seat.
  • (E) Seats legend.
  • (F) “Checkout form”.

 

3B) THE JAVASCRIPT

3b-reservation.js
var reserve = {
  // (A) CHOOSE THIS SEAT
  toggle : seat => seat.classList.toggle("selected"),

  // (B) SAVE RESERVATION
  save : () => {
    // (B1) GET SELECTED SEATS
    var selected = document.querySelectorAll("#layout .selected");

    // (B2) ERROR!
    if (selected.length == 0) {
      alert("No seats selected.");
      return false;
    }

    // (B3) NINJA FORM SUBMISSION
    else {
      var form = document.getElementById("form");
      for (let seat of selected) {
        let input = document.createElement("input");
        input.type = "hidden";
        input.name = "seats[]";
        input.value = seat.innerHTML;
        form.appendChild(input);
      }
      return true;
    }
  }
};

This one just simply inserts the selected seats into the HTML form before submission.

 

 

PART 4) “CHECKOUT”

4-save.php
<?php
// (A) LOAD LIBRARY
require "2-bus-lib.php";

// (B) SAVE
echo $_BUS->reserve(
  $_POST["tid"], $_POST["uid"], $_POST["email"], $_POST["name"], $_POST["seats"]
) ? "OK" : "ERROR" ;
// print_r($_POST);

Right, this dummy “checkout page” simply saves the booking request. Complete your own –

  • Require the customer to pay first?
  • Send a confirmation email?
  • User registration required?
  • Show a nice “thank you” page.

You decide.

 

EXTRAS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

COMPLETE YOUR OWN SYSTEM!

I can hear the trolls singing “this is not a complete system”! Well, this is a simple tutorial, there are plenty of things to consider:

  • If you don’t already have an existing user system, see the links below.
  • If you don’t already have an existing admin panel, see the links below.
  • Decide if you require users to be registered before allowing them to book, open for public booking (no registration required), or auto register when they “checkout”.
  • Decide if you want to restrict the number of seats a customer can book, or if they need to manually call to book the entire bus.
  • Complete your own online payment if you require customers to pay before booking.
  • Complete your own processes – Send email confirmation? Send SMS? Verifications required for cross-border services? Documents?
  • Do your own reports.
  • Beef up on your own security and checks.

It is impossible to create a “one size fits all system”, and I cannot provide free consultation for everyone – “Complete the system” is your own homework.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

6 thoughts on “Simple Bus Ticket Booking System In PHP (Free Download)”

  1. Hello sir , i have imported 1-database.sql on phpmyadmin database and tried to run the 3a-reservation.php but it shows
    “Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table ‘test.trips’ doesn’t exist in C:\xampp\htdocs\PHP\2-bus-lib.php:25 Stack trace: #0 C:\xampp\htdocs\PHP\2-bus-lib.php(25): PDOStatement->execute(Array) #1 C:\xampp\htdocs\PHP\2-bus-lib.php(51): Bus->query(‘SELECT * FROM `…’, Array) #2 C:\xampp\htdocs\PHP\3a-reservation.php(17): Bus->get(1) #3 {main} thrown in C:\xampp\htdocs\PHP\2-bus-lib.php on line 25”
    this error can you please lead us with this problem.

  2. Hello sir! I need bus ticket reservation system in php with algorithm.. can you have this project?? If you have thn can you plzz help me??

Leave a Comment

Your email address will not be published. Required fields are marked *