Features

This tutorial shows how to implement your own hotel room booking system using DayPilot Pro JavaScript Scheduler component. It has a modern JavaScript/HTML5 frontend which communicates with the server using a REST API implemented in PHP/MySQL.

  • Use drag and drop to create, move and update reservations

  • See the reservations and available slots using a scheduling calendar component

  • Delete reservations using a built-in icon

  • Edit reservation details using a modal dialog

  • Overlapping reservations are blocked to prevent overbooking

  • Each hotel room has a status (Ready, Cleanup, Dirty) which is highlighted using a color code

  • The receptionists can filter the hotel room by capacity

  • Each reservation has a status (New, Confirmed, Arrived, CheckedOut, Expired), highlighted using a custom bar color

  • The server-side REST API is implemented in PHP (source code included) that uses MySQL to store the data

  • The front desk user interface is built using HTML5 Scheduler that provides a visual overview of all reservations

  • The project includes a trial version of DayPilot Pro for JavaScript

License

Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.

Scheduler UI Builder

javascript scheduler configurator ui builder

NEW: You can use Scheduler UI Builder online app to create a quick prototype of your new scheduling project. Configure the Scheduler UI in minutes and generate a downloadable HTML5/JavaScript project. See also a tutorial on using the scheduler configurator.

JavaScript Scheduler Initialization

html5 hotel room booking javascript php mysql initialization

We will start the implementation of the booking system front-end by creating a new JavaScript Scheduler instance. The Scheduler is a web calendar component that will display the reservation data for all rooms. As the first step, we will create an empty Scheduler without any data:

HTML5/JavaScript

<div id="dp"></div>

<script>
  const dp = new DayPilot.Scheduler("dp");
  dp.init();
</script>

The default configuration displays an empty timeline with the default scale (one cell per hour) and without any resources (rooms).

Adjusting Scheduler Scale and Time Headers

html5 hotel room booking javascript php mysql scale time headers

Our hotel reservation application will work with days as the basic time unit. We need to switch the Scheduler scale to "Days" and display months and days in the time header rows.

<div id="dp"></div>
      
<script type="text/javascript">

  const dp = new DayPilot.Scheduler("dp");
  dp.startDate = DayPilot.Date.today().firstDayOfMonth();
  dp.days = DayPilot.Date.today().daysInMonth();
  dp.scale = "Day";
  dp.timeHeaders = [
      { groupBy: "Month", format: "MMMM yyyy" },
      { groupBy: "Day", format: "d" }
  ];
  dp.init();

</script>

Loading Hotel Rooms

html5 hotel room booking javascript php mysql loading rooms

We want to display the hotel rooms as Scheduler resources on the vertical (Y) axis. The room data is stored in the MySQL database and we need to load it from the server using an API call. We can use DayPilot.Http.get() to load the room data using an HTTP call:

JavaScript

async function loadRooms() {
    const {data} = await DayPilot.Http.get("backend_rooms.php");
    dp.resources = data;
    dp.update();
}

The Scheduler also provides a shortcut rows.load() method that lets us simplify the room loading function:

function loadRooms() {
  dp.rows.load("backend_rooms.php");
}

The server-side backend_rooms.php script returns the hotel room data in JSON format. A sample response looks like this (five hotel rooms are defined):

[
  {"id":"1","name":"Room 1","capacity":2,"status":"Dirty"},
  {"id":"2","name":"Room 2","capacity":2,"status":"Cleanup"},
  {"id":"3","name":"Room 3","capacity":2,"status":"Ready"},
  {"id":"4","name":"Room 4","capacity":4,"status":"Ready"},
  {"id":"5","name":"Room 5","capacity":1,"status":"Ready"}
]

The PHP script loads the rooms from MySQL database and returns a JSON array. In addition to the required properties (id and name), the response also includes additional room data (status and capacity) which we will use later to customize the front desk view.

backend_rooms.php

<?php
require_once '_db.php';

$json = file_get_contents('php://input');
$params = json_decode($json);

$capacity = isset($params->capacity) ? $params->capacity : '0';

$stmt = $db->prepare("SELECT * FROM rooms WHERE capacity = :capacity OR :capacity = '0' ORDER BY name");
$stmt->bindParam(':capacity', $capacity); 
$stmt->execute();
$rooms = $stmt->fetchAll();

class Room {}

$result = array();

foreach($rooms as $room) {
  $r = new Room();
  $r->id = $room['id'];
  $r->name = $room['name'];
  $r->capacity = intval($room['capacity']);
  $r->status = $room['status'];
  $result[] = $r;
}

header('Content-Type: application/json');
echo json_encode($result);

Hotel Room Capacity and Status

html5 hotel room booking javascript php mysql columns capacity

Our application stores additional room information in the database (capacity, status). We want to display it in the reservation overview in custom row header columns. The columns can be defined using rowHeaderColumns property.

JavaScript

dp.rowHeaderColumns = [
  {title: "Room", display:"name"},
  {title: "Capacity", display: "capacity"},
  {title: "Status", display: "status"}
];

The display property of rowHeaderColumns items specifies the resource/row property that will be used for the column content. The resources are defined as follows (we load the rooms using rows.load() method above):

[
  {"id":"1","name":"Room 1","capacity":2,"status":"Dirty"},
  {"id":"2","name":"Room 2","capacity":2,"status":"Cleanup"},
  {"id":"3","name":"Room 3","capacity":2,"status":"Ready"},
  {"id":"4","name":"Room 4","capacity":4,"status":"Ready"},
  {"id":"5","name":"Room 5","capacity":1,"status":"Ready"}
]

We will further customize the row header cells using onBeforeRowHeaderRender event handler. We will use it to customize the "Capacity" column text and add a custom CSS class to the rows specifying the status:

JavaScript

dp.onBeforeRowHeaderRender = (args) => {
    const beds = (count) => {
        return count + " bed" + (count > 1 ? "s" : "");
    };

    args.row.columns[1].html = beds(args.row.data.capacity);
    switch (args.row.data.status) {
        case "Dirty":
            args.row.cssClass = "status_dirty";
            break;
        case "Cleanup":
            args.row.cssClass = "status_cleanup";
            break;
    }

    args.row.columns[0].areas = [
        {right: 3, top: 3, width: 16, height: 16, cssClass: "area-menu", action: "ContextMenu", visibility: "Hover"}
    ];

};

We have added custom CSS classes to the room headers depending on the room status ("status_dirty", "status_cleanup").

Our Scheduler component uses the built-in CSS theme ("scheduler_default"). We can extend the theme by overriding specified classes. This will let us modify the row appearance depending on the room status.

<style type="text/css">
  .scheduler_default_rowheader_inner
  {
      border-right: 1px solid #ccc;
  }
  .scheduler_default_rowheader.scheduler_default_rowheadercol2
  {
      background: #fff;
  }
  .scheduler_default_rowheadercol2 .scheduler_default_rowheader_inner
  {
      top: 2px;
      bottom: 2px;
      left: 2px;
      background-color: transparent;
      border-left: 5px solid #1a9d13; /* green */
      border-right: 0px none;
  }
  .status_dirty.scheduler_default_rowheadercol2 .scheduler_default_rowheader_inner
  {
      border-left: 5px solid #ea3624; /* red */
  }
  .status_cleanup.scheduler_default_rowheadercol2 .scheduler_default_rowheader_inner
  {
      border-left: 5px solid #f9ba25; /* orange */
  }
</style>

Loading Reservations from MySQL Database

html5 hotel room booking javascript php mysql loading reservations

Now we want to load the reservations (events) from MySQL database. Again, we will use a call to the REST API and update the view as soon as the response arrives.

JavaScript

async function loadReservations() {
  const start = dp.visibleStart();
  const end = dp.visibleEnd();

  const {data} = await DayPilot.Http.get(`backend_reservations.php?start=${start}&end=${end}`);
  dp.events.list = data;
  dp.update();
}

We can also replace the HTTP call with the built-in events.load() method that loads the events from the specified URL (the start and end query string parameters with the visible start and end dates will be added automatically):

dp.events.load("backend_reservations.php");

The server-side backend_reservations.php script returns a JSON array with booking data. Sample JSON output:

[
  {
    "id": "2",
    "text": "Mr. García",
    "start": "2021-09-06T12:00:00",
    "end": "2021-09-11T12:00:00",
    "resource": "2",
    "bubbleHtml": "Reservation details: <br/>Mr. García",
    "status": "Confirmed",
    "paid": "0"
  },
  {
    "id": "3",
    "text": "Mrs. Jones",
    "start": "2021-09-05T12:00:00",
    "end": "2021-09-09T12:00:00",
    "resource": "4",
    "bubbleHtml": "Reservation details: <br/>Mrs. Jones",
    "status": "New",
    "paid": "0"
  },
  {
    "id": "4",
    "text": "Mr. Gray",
    "start": "2021-09-02T12:00:00",
    "end": "2021-09-06T12:00:00",
    "resource": "3",
    "bubbleHtml": "Reservation details: <br/>Mr. Gray",
    "status": "CheckedOut",
    "paid": "100"
  },
  {
    "id": "5",
    "text": "Mrs. Schwartz",
    "start": "2021-09-07T12:00:00",
    "end": "2021-09-12T12:00:00",
    "resource": "3",
    "bubbleHtml": "Reservation details: <br/>Mrs. Schwartz",
    "status": "New",
    "paid": "0"
  },
  {
    "id": "6",
    "text": "Mr. Laurent",
    "start": "2021-09-04T12:00:00",
    "end": "2021-09-09T12:00:00",
    "resource": "1",
    "bubbleHtml": "Reservation details: <br/>Mr. Laurent",
    "status": "Arrived",
    "paid": "50"
  }
]

The PHP backend endpoint uses the start and end query string parameters to filter the reservation records.

backend_reservations.php

<?php
require_once '_db.php';

$start = $_GET['start'];
$end = $_GET['end'];

$stmt = $db->prepare("SELECT * FROM reservations WHERE NOT ((end <= :start) OR (start >= :end))");
$stmt->bindParam(':start', $start);
$stmt->bindParam(':end', $end);
$stmt->execute();
$result = $stmt->fetchAll();

class Event {}
$events = array();

date_default_timezone_set("UTC");
$now = new DateTime("now");
$today = $now->setTime(0, 0, 0);

foreach($result as $row) {
    $e = new Event();
    $e->id = $row['id'];
    $e->text = $row['name'];
    $e->start = $row['start'];
    $e->end = $row['end'];
    $e->resource = $row['room_id'];
    $e->bubbleHtml = "Reservation details: <br/>".$e->text;
    
    // additional properties
    $e->status = $row['status'];
    $e->paid = intval($row['paid']);
    $events[] = $e;
}

header('Content-Type: application/json');
echo json_encode($events);

You can see that we are loading a couple of additional reservation parameters (status, paid) so we can display them in the front desk view.

Displaying Room Reservation Status

html5 hotel room booking javascript php mysql reservation status

The reservation box appearance can be customized using onBeforeEventRender event handler. We will set custom duration bar color and text, depending on the reservation status.

dp.onBeforeEventRender = (args) => {
    const start = new DayPilot.Date(args.data.start);
    const end = new DayPilot.Date(args.data.end);

    const today = DayPilot.Date.today();
    const now = new DayPilot.Date();

    args.data.html = DayPilot.Util.escapeHtml(args.data.text) + " (" + start.toString("M/d/yyyy") + " - " + end.toString("M/d/yyyy") + ")";

    switch (args.data.status) {
        case "New":
            const in2days = today.addDays(1);

            if (start < in2days) {
                args.data.barColor = '#cc0000';
                args.data.toolTip = 'Expired (not confirmed in time)';
            }
            else {
                args.data.barColor = '#e69138';
                args.data.toolTip = 'New';
            }
            break;
        case "Confirmed":
            const arrivalDeadline = today.addHours(18);

            if (start < today || (start.getDatePart() === today.getDatePart() && now > arrivalDeadline)) { // must arrive before 6 pm
                args.data.barColor = "#cc4125";  // red
                args.data.toolTip = 'Late arrival';
            }
            else {
                args.data.barColor = "#38761d";
                args.data.toolTip = "Confirmed";
            }
            break;
        case 'Arrived': // arrived
            const checkoutDeadline = today.addHours(10);

            if (end < today || (end.getDatePart() === today.getDatePart() && now > checkoutDeadline)) { // must checkout before 10 am
                args.data.barColor = "#cc4125";  // red
                args.data.toolTip = "Late checkout";
            }
            else
            {
                args.data.barColor = "#1691f4";  // blue
                args.data.toolTip = "Arrived";
            }
            break;
        case 'CheckedOut': // checked out
            args.data.barColor = "gray";
            args.data.toolTip = "Checked out";
            break;
        default:
            args.data.toolTip = "Unexpected state";
            break;
    }

    args.data.html = "<div>" + args.data.html + "<br /><span style='color:gray'>" + args.data.toolTip + "</span></div>";

    const paid = args.data.paid;
    const paidColor = "#aaaaaa";

    args.data.areas = [
        { bottom: 10, right: 4, html: "<div style='color:" + paidColor + "; font-size: 8pt;'>Paid: " + paid + "%</div>", v: "Visible"},
        { left: 4, bottom: 8, right: 4, height: 2, html: "<div style='background-color:" + paidColor + "; height: 100%; width:" + paid + "%'></div>", v: "Visible" }
    ];

};

Filtering Hotel Rooms by Capacity

html5 hotel room booking javascript php mysql room filter

Our room booking application will support filtering the hotel rooms by capacity. We can implement the room filter using a simple drop-down list.

For a detailed tutorial on more advanced room filtering, please see JavaScript/HTML5 Scheduler: Filtering Rooms by Availability. It explains how to implement multi-parameter filters and find rooms of a specified size that are available for a given date

HTML5/JavaScript

Room filter:
<select id="filter">
    <option value="0">All</option>
    <option value="1">Single</option>
    <option value="2">Double</option>
    <option value="4">Family</option>
</select>

<script>
  const elements = {
      filter: document.querySelector("#filter"),
      // ...
  };

  elements.filter.addEventListener("change", (e) => {
      loadRooms();
  });
</script>

html5 hotel room booking javascript php mysql room filter single

The filtering logic is implemented on the server side, in the backend_rooms.php script. We need to extend loadRooms() method and backend_rooms.php to support the room capacity filter.

The selected filter value is added to the request URL as capacity query string parameter.

JavaScript

async function loadRooms() {
    const {data} = await DayPilot.Http.post("backend_rooms.php", { capacity: elements.filter.value });
    dp.resources = data;
    dp.update();
}

backend_rooms.php

<?php
require_once '_db.php';

$json = file_get_contents('php://input');
$params = json_decode($json);

$capacity = isset($params->capacity) ? $params->capacity : '0';

$stmt = $db->prepare("SELECT * FROM rooms WHERE capacity = :capacity OR :capacity = '0' ORDER BY name");
$stmt->bindParam(':capacity', $capacity); 
$stmt->execute();
$rooms = $stmt->fetchAll();

class Room {}

$result = array();

foreach($rooms as $room) {
  $r = new Room();
  $r->id = $room['id'];
  $r->name = $room['name'];
  $r->capacity = intval($room['capacity']);
  $r->status = $room['status'];
  $result[] = $r;
}

header('Content-Type: application/json');
echo json_encode($result);

Creating Room Reservations using Drag and Drop

html5 hotel room booking javascript php mysql create reservation

The front desk workers should be able to create a new room reservation using drag and drop. Drag and drop time range selecting is already enabled, we just need to add the event handler.

JavaScript

dp.onTimeRangeSelected = async (args) => {

    const rooms = dp.resources.map((item) => {
        return {
            name: item.name,
            id: item.id
        };
    });

    const form = [
        {name: "Text", id: "text"},
        {name: "Start", id: "start", dateFormat: "MM/dd/yyyy HH:mm tt"},
        {name: "End", id: "end", dateFormat: "MM/dd/yyyy HH:mm tt"},
        {name: "Room", id: "resource", options: rooms},
    ];

    const data = {
        start: args.start,
        end: args.end,
        resource: args.resource
    };

    const modal = await DayPilot.Modal.form(form, data);

    dp.clearSelection();
    if (modal.canceled) {
        return;
    }
    const e = modal.result;

    const {data: result} = await DayPilot.Http.post("backend_reservation_create.php", e);

    e.id = result.id;
    e.paid = result.paid;
    e.status = result.status;
    dp.events.add(e);

};

The event handler opens a modal dialog built using DayPilot.Modal.form(). That will let users enter the reservations details:

html5 hotel room booking javascript php mysql new reservation modal

As soon as the user hits [OK] we create the new reservation using an HTTP call to backend_reservation_create.php script.

backend_reservation_create.php

<?php
require_once '_db.php';

$stmt = $db->prepare("INSERT INTO reservations (name, start, end, room_id, status, paid) VALUES (:name, :start, :end, :room, 'New', 0)");
$stmt->bindParam(':start', $_POST['start']);
$stmt->bindParam(':end', $_POST['end']);
$stmt->bindParam(':name', $_POST['name']);
$stmt->bindParam(':room', $_POST['room']);
$stmt->execute();

class Result {}

$response = new Result();
$response->result = 'OK';
$response->message = 'Created with id: '.$db->lastInsertId();
$response->id = $db->lastInsertId();

header('Content-Type: application/json');
echo json_encode($response);

Editing Room Reservation Details

html5 hotel room booking javascript php mysql edit reservation modal

In order to let the receptionists edit the reservation details we add a new event click handler that opens a modal dialog with reservation information.

dp.onEventClick = async (args) => {
    const rooms = dp.resources.map((item) => {
        return {
            name: item.name,
            id: item.id
        };
    });

    const statuses = [
        {name: "New", id: "New"},
        {name: "Confirmed", id: "Confirmed"},
        {name: "Arrived", id: "Arrived"},
        {name: "CheckedOut", id: "CheckedOut"}
    ];

    const paidoptions = [
        {name: "0%", id: 0},
        {name: "50%", id: 50},
        {name: "100%", id: 100},
    ]

    const form = [
        {name: "Text", id: "text"},
        {name: "Start", id: "start", dateFormat: "MM/dd/yyyy h:mm tt"},
        {name: "End", id: "end", dateFormat: "MM/dd/yyyy h:mm tt"},
        {name: "Room", id: "resource", options: rooms},
        {name: "Status", id: "status", options: statuses},
        {name: "Paid", id: "paid", options: paidoptions},
    ];

    const data = args.e.data;

    const modal = await DayPilot.Modal.form(form, data);

    dp.clearSelection();
    if (modal.canceled) {
        return;
    }
    const e = modal.result;
    await DayPilot.Http.post("backend_reservation_update.php", e);
    dp.events.update(e);
};

The modal dialog logic is the same as in case of creating new reservations. We update the reservation details in the database using an HTTP call to backend_reservation_update.php.

backend_reservation_update.php

<?php
require_once '_db.php';

$json = file_get_contents('php://input');
$params = json_decode($json);

$stmt = $db->prepare("UPDATE reservations SET name = :name, start = :start, end = :end, room_id = :room, status = :status, paid = :paid WHERE id = :id");

$stmt->bindParam(':id', $params->id);
$stmt->bindParam(':start', $params->start);
$stmt->bindParam(':end', $params->end);
$stmt->bindParam(':name', $params->text);
$stmt->bindParam(':room', $params->resource);
$stmt->bindParam(':status', $params->status);
$stmt->bindParam(':paid', $params->paid);
$stmt->execute();

class Result {}

$response = new Result();
$response->result = 'OK';
$response->message = 'Update successful';

header('Content-Type: application/json');
echo json_encode($response);

Moving Reservations using Drag and Drop

html5 hotel room booking javascript php mysql moving reservation drag drop

The reservations can be moved using drag and drop. Whenever the reservation is dropped at a new location, onEventMoved handler is fired.

JavaScript

dp.onEventMoved = async (args) => {
    const params = {
        id: args.e.id(),
        newStart: args.newStart,
        newEnd: args.newEnd,
        newResource: args.newResource
    };

    const {data} = await DayPilot.Http.post("backend_reservation_move.php", params);
    dp.message(data.message);

};

We call backend_reservation_move.php REST API endpoint to save the new reservation date in the MySQL database.

backend_reservation_move.php

<?php
require_once '_db.php';

$json = file_get_contents('php://input');
$params = json_decode($json);

class Result {}

$stmt = $db->prepare("SELECT * FROM reservations WHERE NOT ((end <= :start) OR (start >= :end)) AND id <> :id AND room_id = :resource");
$stmt->bindParam(':start', $params->newStart);
$stmt->bindParam(':end', $params->newEnd);
$stmt->bindParam(':id', $params->id);
$stmt->bindParam(':resource', $params->newResource);
$stmt->execute();
$overlaps = $stmt->rowCount() > 0;

if ($overlaps) {
    $response = new Result();
    $response->result = 'Error';
    $response->message = 'This reservation overlaps with an existing reservation.';

    header('Content-Type: application/json');
    echo json_encode($response);
    exit;
}

$stmt = $db->prepare("UPDATE reservations SET start = :start, end = :end, room_id = :resource WHERE id = :id");
$stmt->bindParam(':start', $params->newStart);
$stmt->bindParam(':end', $params->newEnd);
$stmt->bindParam(':id', $params->id);
$stmt->bindParam(':resource', $params->newResource);
$stmt->execute();


$response = new Result();
$response->result = 'OK';
$response->message = 'Update successful';

header('Content-Type: application/json');
echo json_encode($response);

Preventing Reservation Overlaps

html5 hotel room booking javascript php mysql reservation overlaps

As we don't want to allow overlapping reservations (double booking of a room) we will disable event overlapping.

dp.allowEventOverlap = false;

This will prevent moving or resizing a reservation over existing reservations and selecting a date that has been already booked.

Deleting Room Reservations

html5 hotel room booking javascript php mysql deleting reservations

The reservations can be deleted using an icon in the upper-right event box. 

We need to enabled this feature using eventDeleteHandling property and add an onEventDeleted handler.

JavaScript

dp.eventDeleteHandling = "Update";

dp.onEventDeleted = async (args) => {
    await DayPilot.Http.post("backend_reservation_delete.php", {id: args.e.id()});
    dp.message("Deleted.");
};

The event handler will call backend_reservation_delete.php to save the changes in the database.

backend_reservation_delete.php

<?php
require_once '_db.php';

$json = file_get_contents('php://input');
$params = json_decode($json);

$stmt = $db->prepare("DELETE FROM reservations WHERE id = :id");
$stmt->bindParam(':id', $params->id);
$stmt->execute();

class Result {}

$response = new Result();
$response->result = 'OK';
$response->message = 'Delete successful';

header('Content-Type: application/json');
echo json_encode($response);

Changing the Date

html5 hotel room booking javascript php mysql changing date

We will let the front end clerks change the visible date by selecting it using a Navigator control.

HTML5

<div id="nav"></div>

JavaScript

<script type="text/javascript">
  const nav = new DayPilot.Navigator("nav");
  nav.selectMode = "Month";
  nav.showMonths = 3;
  nav.skipMonths = 3;
  nav.onTimeRangeSelected = function(args) {
      loadTimeline(args.start);
      dp.update();
      loadReservations();
  };
  nav.init();
</script>

html5 hotel room booking javascript php mysql date range

The receptionists will also be able to change the visible date range using a drop-down list.

HTML5

Time range: 
<select id="timerange">
    <option value="week">Week</option>
    <option value="month" selected>Month</option>
</select>

JavaScript

elements.timerange.addEventListener("change", () => {
    switch (this.value) {
        case "week":
            dp.days = 7;
            nav.selectMode = "Week";
            nav.select(nav.selectionDay);
            break;
        case "month":
            dp.days = dp.startDate.daysInMonth();
            nav.selectMode = "Month";
            nav.select(nav.selectionDay);
            break;
    }
});

Hotel Room Check-In and Check-Out Time

html5 hotel room booking javascript php mysql standard check in

Normally, the Scheduler generates the timeline automatically from startDate and days properties. The day cells in the standard timeline always start at 00:00 and end and 24:00.

html5 hotel room booking javascript php mysql custom check in

Hotel reservation systems need to work custom check-in and check-out times which are usually around noon. In order to display the check-in/check-out deadlines we will create the Scheduler timeline manually and create the timeline cells one-by-one. The check-in and the check-out times are set to 12:00 (noon).

function loadTimeline(date) {
    dp.scale = "Manual";
    dp.timeline = [];
    const start = date.getDatePart().addHours(12);

    for (let i = 0; i < dp.days; i++) {
        dp.timeline.push({start: start.addDays(i), end: start.addDays(i+1)});
    }
}

It is necessary to use a time header with groupBy: "Day" modifier. The default value (groupBy: "Cell") would align the day header with the grid cells.

dp.timeHeaders = [
  { groupBy: "Month", format: "MMMM yyyy" },
  { groupBy: "Day", format: "d" }
];

Database (MySQL, SQLite)

The sample project includes a PDO implementation of the database access for two databases:

  • MySQL (_db_mysql.php)

  • SQLite (_db_sqlite.php)

The default database engine (_db.php) is SQLite:

<?php

// use sqlite
require_once '_db_sqlite.php';

// use MySQL
//require_once '_db_mysql.php';

You can switch to MySQL by changing _db.php as follows:

 <?php

// use sqlite
// require_once '_db_sqlite.php';

// use MySQL
require_once '_db_mysql.php';

Don't forget to adjust the database connection properties (server, database name, username, password, port) in _db_mysql.php.

The MySQL script will create rooms and reservations tables in the target database (if they don't exist already).

MySQL Database Schema

CREATE TABLE IF NOT EXISTS rooms (
  id INTEGER PRIMARY KEY AUTO_INCREMENT, 
  name TEXT, 
  capacity INTEGER,
  status VARCHAR(30));

CREATE TABLE IF NOT EXISTS reservations (
  id INTEGER PRIMARY KEY AUTO_INCREMENT, 
  name TEXT, 
  start DATETIME, 
  end DATETIME,
  room_id INTEGER,
  status VARCHAR(30),
  paid INTEGER);

History

  • June 7, 2021: DayPilot Pro 2021.2.5000, ES6 syntax, using async/await for promise calls, using system fonts

  • November 3, 2020: DayPilot Pro 2020.4.4736, room sorting, room context menu, room deleting, modal dialogs use DayPilot.Modal.form(), XSS protection, jQuery removed

  • May 13, 2020: DayPilot Pro version updated (2020.2.4459), using Tabular mode.

  • October 21, 2019: Minor fixes. Inline code snippets highlighted.

  • September 6, 2019: DayPilot Pro version updated (2019.3.3997). Updated look. New screenshots.

  • May 22, 2019: DayPilot Pro version updated (2019.2.3851). Event HTML updated.

  • February 17, 2018: DayPilot Pro version updated (2018.1.3169). _db.php using requireonce to select DB backend (SQLite/MySQL)

  • January 26, 2017:  DayPilot Pro version updated (8.2.2661).

  • June 8, 2016: onBeforeEventRender fixed (missing "now" declaration). Updated with the latest DayPilot Pro version (8.2.2200).

  • December 8, 2015: MySQL DB schema fixed (auto incrementing room id).

  • November 16, 2015: DayPilot bug fixed (moving existing events over today).

  • November 12, 2015: Navigator added, room creating and editing.

  • October 1, 2015: Incorrect start and end dates in loadEvents() fixed.

  • September 30, 2014: Initial release, based on Hotel Room Booking Tutorial (ASP.NET, C#, VB.NET, SQL Server)