PHP Event Calendar using FullCalendar JS Library

The Event Calendar lists the events date-wise in a large calendar view. The events are fetched dynamically and listed under the date cell. An event calendar makes it easier to find the events for a specific date. You can build a custom event calendar with dynamic data using PHP and MySQL. In the previous tutorial, we learn how to build an event calendar with PHP and MySQL. This tutorial will show you how to create an event calendar with PHP using the FullCalendar JavaScript library.

FullCalendar is a JavaScript library that helps to integrate a Full-sized event calendar on a website quickly. It provides a user-friendly way to add events to the calendar and display them on the date cell. We will use the FullCalendar library to build an event calendar with PHP and MySQL. Not only the event listing but also we will integrate CRUD functionality with FullCalendar.

The following functionality will be implemented to build PHP event calendar with FullCalendar.

  • Fetch events data from the MySQL database.
  • Create a large calendar with FullCalendar JS library.
  • Display events in the date cell of the calendar.
  • View, add, edit, update, and delete events from the calendar.

Before getting started, take a look at the file structure of the PHP event calendar with FullCalendar JS plugin script.

php_event_calendar_with_fullcalendar/
├── index.html
├── fetchEvents.php
├── eventHandler.php
├── dbConfig.php
├── js/
│   ├── fullcalendar/
│   └── sweetalert2.all.min.js
└── css/
    └── style.css

Create Database Table

To display the dynamic events in the calendar, the event data need to be stored in the database. The following SQL creates a events table with some basic fields in the MySQL database.

CREATE TABLE `events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL,
  `url` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `start` date NOT NULL,
  `end` date NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Database Configuration (dbConfig.php)

This file is used to connect with the database using PHP and MySQL. Specify the database host (DB_HOST), username (DB_USERNAME), password (DB_PASSWORD), and name (DB_NAME) as per your database credentials.

<?php  
// Database configuration 
define('DB_HOST''MySQL_Database_Host');
define('DB_USERNAME''MySQL_Database_Username');
define('DB_PASSWORD''MySQL_Database_Password');
define('DB_NAME''MySQL_Database_Name');
 
// Create database connection 
$db = new mysqli(DB_HOSTDB_USERNAMEDB_PASSWORDDB_NAME); 
 
// Check connection 
if ($db->connect_error) {
    die(
"Connection failed: " $db->connect_error); 
}

Build Event Calendar (index.html)

Dialog Boxes: Include the sweetalert2 plugin library to initialize and use it for popup boxes.

<script src="js/sweetalert2.all.min.js"></script>

Calendar Plugin: Include FullCalendar JS & CSS library to build full-sized calendar using JavaScript.

<link href="js/fullcalendar/lib/main.css" rel="stylesheet" />
<script src="js/fullcalendar/lib/main.js"></script>

Calendar Container: Define an HTML element to attach the event calendar.

<div id="calendar"></div>

Initialize the FullCalendar class on the DOMContentLoaded event and render the calendar on the web page.

<script>
document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'dayGridMonth',
    height: 650,
  });

  calendar.render();
});
</script>

In the following examples, we will see how to integrate event listing, details, add, and delete functionality to FullCalendar using JavaScript.

Fetch events from the server-side and list them on the Calendar:

  • Use the events option in FullCalendar configurations to set the server-side script URL (fetchEvents.php) that the calendar will fetch the event data from.
  • The data must be provided as a JSON feed.
document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'dayGridMonth',
    height: 650,
    events: 'fetchEvents.php',
  });

  calendar.render();
});

Add Event:

  • Use select callback function to attach Event Add feature.
  • The selectable option must be set to true which makes the date cell selectable.
  • Swal.fire() method is used to display popup boxes.
  • On select, the popup will appear with input fields (title, description, and URL).
  • After the submission, the event data is posted to the server-side script (eventHandler.php) via HTTP POST request using JavaScript Fetch API.
  • Based on the status, the message is shown on the popup.
  • The calendar.refetchEvents() method is called to fetch the updated events list.
document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
	initialView: 'dayGridMonth',
	height: 650,
	events: 'fetchEvents.php',

	selectable: true,
	select: async function (start, end, allDay) {
	  const { value: formValues } = await Swal.fire({
		title: 'Add Event',
		html:
		  '<input id="swalEvtTitle" class="swal2-input" placeholder="Enter title">' +
		  '<textarea id="swalEvtDesc" class="swal2-input" placeholder="Enter description"></textarea>' +
		  '<input id="swalEvtURL" class="swal2-input" placeholder="Enter URL">',
		focusConfirm: false,
		preConfirm: () => {
		  return [
			document.getElementById('swalEvtTitle').value,
			document.getElementById('swalEvtDesc').value,
			document.getElementById('swalEvtURL').value
		  ]
		}
	  });

	  if (formValues) {
		// Add event
		fetch("eventHandler.php", {
		  method: "POST",
		  headers: { "Content-Type": "application/json" },
		  body: JSON.stringify({ request_type:'addEvent', start:start.startStr, end:start.endStr, event_data: formValues}),
		})
		.then(response => response.json())
		.then(data => {
		  if (data.status == 1) {
			Swal.fire('Event added successfully!', '', 'success');
		  } else {
			Swal.fire(data.error, '', 'error');
		  }

		  // Refetch events from all sources and rerender
		  calendar.refetchEvents();
		})
		.catch(console.error);
	  }
	}
  });

  calendar.render();
});

View event details:

  • Use eventClick callback function to attach the event view details feature.
  • On click, the event details are displayed on the popup box.
  • Swal.fire() method is used to display popup boxes.
  • The info.event object is used to get the event details set in Event Objects.
  • The info.event.extendedProps is used to get the additional info from Event Objects.
document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'dayGridMonth',
    height: 650,
    events: 'fetchEvents.php',

    eventClick: function(info) {
      info.jsEvent.preventDefault();
      
      // change the border color
      info.el.style.borderColor = 'red';
      
      Swal.fire({
        title: info.event.title,
        icon: 'info',
        html:'<p>'+info.event.extendedProps.description+'</p><a href="'+info.event.url+'">Visit event page</a>',
      });
    }
  });

  calendar.render();
});

Edit and Delete Event:

  • The Edit button is placed in the event details popup.
    • On edit request, the form appears with the prefilled event data in the input fields.
    • On confirm, the update request is sent to the server-side script (eventHandler.php). The info.event.id is passed to this POST request as the DB reference ID of the selected event, along with the form input data.
  • The Delete button is placed in the event details popup.
    • On confirm, the delete request is sent to the server-side script (eventHandler.php). The info.event.id is passed to this POST request as the DB reference ID of the selected event.
  • Based on the status, the message is shown on the popup.
  • The calendar.refetchEvents() method is called to fetch the updated events list.
document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'dayGridMonth',
    height: 650,
    events: 'fetchEvents.php',
    
    selectable: true,
    select: async function (start, end, allDay) {
      const { value: formValues } = await Swal.fire({
        title: 'Add Event',
        confirmButtonText: 'Submit',
        showCloseButton: true,
		    showCancelButton: true,
        html:
          '<input id="swalEvtTitle" class="swal2-input" placeholder="Enter title">' +
          '<textarea id="swalEvtDesc" class="swal2-input" placeholder="Enter description"></textarea>' +
          '<input id="swalEvtURL" class="swal2-input" placeholder="Enter URL">',
        focusConfirm: false,
        preConfirm: () => {
          return [
            document.getElementById('swalEvtTitle').value,
            document.getElementById('swalEvtDesc').value,
            document.getElementById('swalEvtURL').value
          ]
        }
      });

      if (formValues) {
        // Add event
        fetch("eventHandler.php", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ request_type:'addEvent', start:start.startStr, end:start.endStr, event_data: formValues}),
        })
        .then(response => response.json())
        .then(data => {
          if (data.status == 1) {
            Swal.fire('Event added successfully!', '', 'success');
          } else {
            Swal.fire(data.error, '', 'error');
          }

          // Refetch events from all sources and rerender
          calendar.refetchEvents();
        })
        .catch(console.error);
      }
    },

    eventClick: function(info) {
      info.jsEvent.preventDefault();
      
      // change the border color
      info.el.style.borderColor = 'red';
      
      Swal.fire({
        title: info.event.title,
        icon: 'info',
        html:'<p>'+info.event.extendedProps.description+'</p><a href="'+info.event.url+'">Visit event page</a>',
        showCloseButton: true,
        showCancelButton: true,
        showDenyButton: true,
        cancelButtonText: 'Close',
        confirmButtonText: 'Delete',
        denyButtonText: 'Edit',
      }).then((result) => {
        if (result.isConfirmed) {
          // Delete event
          fetch("eventHandler.php", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ request_type:'deleteEvent', event_id: info.event.id}),
          })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              Swal.fire('Event deleted successfully!', '', 'success');
            } else {
              Swal.fire(data.error, '', 'error');
            }

            // Refetch events from all sources and rerender
            calendar.refetchEvents();
          })
          .catch(console.error);
        } else if (result.isDenied) {
          // Edit and update event
          Swal.fire({
            title: 'Edit Event',
            html:
              '<input id="swalEvtTitle_edit" class="swal2-input" placeholder="Enter title" value="'+info.event.title+'">' +
              '<textarea id="swalEvtDesc_edit" class="swal2-input" placeholder="Enter description">'+info.event.extendedProps.description+'</textarea>' +
              '<input id="swalEvtURL_edit" class="swal2-input" placeholder="Enter URL" value="'+info.event.url+'">',
            focusConfirm: false,
            confirmButtonText: 'Submit',
            preConfirm: () => {
            return [
              document.getElementById('swalEvtTitle_edit').value,
              document.getElementById('swalEvtDesc_edit').value,
              document.getElementById('swalEvtURL_edit').value
            ]
            }
          }).then((result) => {
            if (result.value) {
              // Edit event
              fetch("eventHandler.php", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ request_type:'editEvent', start:info.event.startStr, end:info.event.endStr, event_id: info.event.id, event_data: result.value})
              })
              .then(response => response.json())
              .then(data => {
                if (data.status == 1) {
                  Swal.fire('Event updated successfully!', '', 'success');
                } else {
                  Swal.fire(data.error, '', 'error');
                }

                // Refetch events from all sources and rerender
                calendar.refetchEvents();
              })
              .catch(console.error);
            }
          });
        } else {
          Swal.close();
        }
      });
    }
  });

  calendar.render();
});

Server-side Handler Script with PHP and MySQL

The following code snippet shows how to handle the List/View/Add/Edit/Update/Delete functionality from the server-side using PHP and MySQL.

Fetch Events (fetchEvents.php):

  • Fetch the events from the database.
  • Render event data in JSON format using json_encode() function.
<?php      
// Include database configuration file 
require_once 'dbConfig.php';

// Filter events by calendar date
$where_sql '';
if(!empty(
$_GET['start']) && !empty($_GET['end'])){
    
$where_sql .= " WHERE start BETWEEN '".$_GET['start']."' AND '".$_GET['end']."' ";
}

// Fetch events from database
$sql "SELECT * FROM events $where_sql";
$result $db->query($sql); 

$eventsArr = array();
if(
$result->num_rows 0){
    while(
$row $result->fetch_assoc()){
        
array_push($eventsArr$row);
    }
}

// Render event data in JSON format
echo json_encode($eventsArr);

The eventHandler.php file is used to handle Add and Delete functionality. Based on the request_type param, the code block is executed.

Add Event (eventHandler.php):
The request is accepted if the request_type=addEvent.

  • Retrieve the event details from the POST input fields.
  • Insert event data in the database using MySQL prepare statement.
  • Return status response in JSON format.

Update Event (eventHandler.php):
The request is accepted if the request_type=editEvent.

  • Retrieve the event reference ID from the POST body.
  • Retrieve the event data from the POST input fields.
  • Update event data in the database based on the event id.
  • Return status response in JSON format.

Delete Event (eventHandler.php):
The request is accepted if the request_type=deleteEvent.

  • Retrieve the event reference ID from the POST body.
  • Delete event data from the database.
  • Return status response in JSON format.
<?php 
  
// Include database configuration file 
require_once 'dbConfig.php';

// Retrieve JSON from POST body
$jsonStr file_get_contents('php://input');
$jsonObj json_decode($jsonStr);

if(
$jsonObj->request_type == 'addEvent'){
    
$start $jsonObj->start;
    
$end $jsonObj->end;

    
$event_data $jsonObj->event_data;
    
$eventTitle = !empty($event_data[0])?$event_data[0]:'';
    
$eventDesc = !empty($event_data[1])?$event_data[1]:'';
    
$eventURL = !empty($event_data[2])?$event_data[2]:'';
    
    if(!empty(
$eventTitle)){
        
// Insert event data into the database
        
$sqlQ "INSERT INTO events (title,description,url,start,end) VALUES (?,?,?,?,?)";
        
$stmt $db->prepare($sqlQ);
        
$stmt->bind_param("sssss"$eventTitle$eventDesc$eventURL$start$end);
        
$insert $stmt->execute();

        if(
$insert){
            
$output = [
                
'status' => 1
            
];
            echo 
json_encode($output);
        }else{
            echo 
json_encode(['error' => 'Event Add request failed!']);
        }
    }
}elseif(
$jsonObj->request_type == 'editEvent'){
    
$start $jsonObj->start;
    
$end $jsonObj->end;
    
$event_id $jsonObj->event_id;

    
$event_data $jsonObj->event_data;
    
$eventTitle = !empty($event_data[0])?$event_data[0]:'';
    
$eventDesc = !empty($event_data[1])?$event_data[1]:'';
    
$eventURL = !empty($event_data[2])?$event_data[2]:'';
    
    if(!empty(
$eventTitle)){
        
// Update event data into the database
        
$sqlQ "UPDATE events SET title=?,description=?,url=?,start=?,end=? WHERE id=?";
        
$stmt $db->prepare($sqlQ);
        
$stmt->bind_param("sssssi"$eventTitle$eventDesc$eventURL$start$end$event_id);
        
$update $stmt->execute();

        if(
$update){
            
$output = [
                
'status' => 1
            
];
            echo 
json_encode($output);
        }else{
            echo 
json_encode(['error' => 'Event Update request failed!']);
        }
    }
}elseif(
$jsonObj->request_type == 'deleteEvent'){
    
$id $jsonObj->event_id;

    
$sql "DELETE FROM events WHERE id=$id";
    
$delete $db->query($sql);
    if(
$delete){
        
$output = [
            
'status' => 1
        
];
        echo 
json_encode($output);
    }else{
        echo 
json_encode(['error' => 'Event Delete request failed!']);
    }
}

?>

Build an Event Calendar with PHP using jQuery, Ajax, and MySQL

Conclusion

This guide helps you to create an event calendar with PHP using the FullCalendar plugin. The example code shows how to integrate list/view/add/edit/update/delete functionality with the FullCalendar library using PHP and MySQL. You can allow the user to manage events on a full-sized calendar dynamically. The functionality of the event calendar can be enhanced easily with FullCalendar as per your needs.
If you want to add an event for multiple days, the event creation form requires inputs for FromDate and ToDate. Just submit the service request from the link below for functionality enhancement as needed.

Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request

6 Comments

  1. Abu Sadeq Said...
  2. Gnata Ottavino Said...
  3. Thalion Said...
  4. Troy Said...
  5. Darcy Marie Said...
  6. Dh7382 Said...

Leave a reply

keyboard_double_arrow_up