How to Create a PHP Event Calendar with FullCalendar JS Library

Event calendars are a powerful tool that keeps track of upcoming events, schedules, appointments, and deadlines.

I am using FullCalendar plugin to create a calendar layout and make it dynamic using PHP and MySQL. Plugin is not dependent on any library, responsive, and automatically fits on the page. Different types of options and events are available to customize and control it.

In this tutorial, I show how you can create an event, update and delete an existing event, and load events in the FullCalendar JavaScript library using PHP AJAX and MySQL.

I am using FullCalendar v6 in the example and sweetAlert library to display an alert box to add/edit events.

How to Create a PHP Event Calendar with FullCalendar JS Library


Table of Content

  1. Create a Table
  2. Create a Database connection file
  3. Download and Include FullCalendar
  4. HTML – Setting Up the FullCalendar Container
  5. Create a PHP File to Load All Events in FullCalendar
  6. Create a PHP File to Manage AJAX Requests
  7. jQuery: Initializing FullCalendar and Managing Events
  8. Demo
  9. Conclusion

1. Create a Table

I am using events table in the example. It has the following structure –

CREATE TABLE `events` (
    `id` int(10) NOT NULL,
    `title` varchar(190) NOT NULL,
    `description` text NOT NULL,
    `start_date` date NOT NULL,
    `end_date` date NOT NULL
);

ALTER TABLE `events`
ADD PRIMARY KEY (`id`);

ALTER TABLE `events`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;

2. Create a Database connection file

Create a config.php for database configuration.

<?php

$host = "localhost"; /* Host name */
$user = "root"; /* User */
$password = ""; /* Password */
$dbname = "tutorial"; /* Database name */

$con = mysqli_connect($host, $user, $password,$dbname);
// Check connection
if (!$con) {
    die("Connection failed: " . mysqli_connect_error());
}

3. Download and Include FullCalendar

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>

<!-- Fullcalendar -->
<script type="text/javascript" src="fullcalendar-6.1.4/dist/index.global.min.js"></script>

<!-- Sweetalert -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

4. HTML – Setting Up the FullCalendar Container

Creating an index.php file.

Within this file, use PHP to store the current date in a $currentData variable. This date will be used to set the starting point for FullCalendar.

Next, create <div id='calendar' > to initialize FullCalendar.

<?php 
$currentData = date('Y-m-d');
?>

<!-- Calendar Container -->
<div id='calendar-container'>
    <div id='calendar'></div>
</div>

5. Create a PHP File to Load All Events in FullCalendar

  • Create fetchevents.php file to load all created events list in FullCalendar.
  • Retrieve all event records from the events table. This gathered information will be stored in the $eventsList variable.
  • Loop through the $eventsList. During each iteration, gather key event details such as ‘eventid’, ‘title’, ‘description’, ‘start’, and ‘end’ dates. These details will be compiled into a convenient $response array.
  • To ensure seamless integration with FullCalendar, convert the $response array into JSON format.
<?php

include "config.php";

// Fetch all records
$sql = "SELECT * FROM events";
$eventsList = mysqli_query($con,$sql);

$response = array();
while($row = mysqli_fetch_assoc($eventsList)){
    $response[] = array(
        "eventid" => $row['id'],
        "title" => $row['title'],
        "description" => $row['description'],
        "start" => $row['start_date'],
        "end" => $row['end_date'],
    );
}

echo json_encode($response);
exit;

6. Create a PHP File to Manage AJAX Requests

Create ajaxfile.php file to handle 4 requests:

1. Adding a New Event (addEvent)

  • Reading the POST data and assigning it to variables.
  • Check if the required variables have non-empty values.
  • If all conditions are met, insert a new record into the events table.
  • Capture the last inserted ID in the $eventid variable and set $status to 1.
  • Construct a $response array with keys such as ‘eventid’, ‘status’ and ‘message’. Assign the $eventid to the 'eventid' key, set 'status' to 1, and provide a success message.
  • In case the record isn’t inserted, set $status to 0 and include an error message.
  • Return the $response array in JSON format.

2. Updating Event Dates (moveEvent)

  • Retrieve the new dates from the POST request and update the relevant event’s ID.
  • Ensure $eventid is greater than 0 and that both start_date and end_date are not empty.
  • Check if the event ID exists in the events table. If it does, update the start_date and end_date fields and set $status to 1.
  • In the $response array, set ‘status’ to 1 and provide a success message upon successful update.
  • If the update fails, set ‘status’ to 0 and include an error message.
  • Return the $response array in JSON format.

3. Editing Event Details (editEvent)

  • Read the POST data containing event details and update the corresponding event ID.
  • Ensure $eventid is greater than 0 and that both ‘title’ and ‘description’ are not empty.
  • Check if the event ID exists in the events table. If it does, update the ‘title’ and ‘description’ fields with the new POST values.
  • Set $status to 1 and construct the $response array with ‘status’ set to 1 and a success message.
  • If the update fails, set ‘status’ to 0 and include an error message.
  • Return the $response array in JSON format.

4. Deleting an Event (deleteEvent)

  • Read the POST event ID and verify if it’s greater than 0.
  • Check if the event ID exists in the events table. If it does, delete the corresponding record and set $status to 1.
  • In the $response array, set ‘status’ to 1 and provide a success message upon successful deletion.
  • If deletion fails, set ‘status’ to 0 and include an error message.
  • Return the $response array in JSON format.
<?php

include "config.php";

$request = "";

// Read $_GET value
if(isset($_POST['request'])){
     $request = $_POST['request'];
}

// Add New event 
if($request == 'addEvent'){

     // POST data
     $title = ""; $description = ""; 
     $start_date = ""; $end_date = "";

     if(isset($_POST['title'])){
          $title = $_POST['title'];
     }
     if(isset($_POST['description'])){
          $description = $_POST['description'];
     }
     if(isset($_POST['start_date'])){
          $start_date = $_POST['start_date'];
     }
     if(isset($_POST['start_date'])){
          $end_date = $_POST['end_date'];
     }

     $response = array();
     $status = 0;
     if(!empty($title) && !empty($description) && !empty($start_date) && !empty($end_date) ){

          // Insert record
          $sql = "INSERT INTO events(title,description,start_date,end_date) VALUES('".$title."','".$description."','".$start_date."','".$end_date."')";
          if(mysqli_query($con,$sql)){
               $eventid = mysqli_insert_id($con);

               $status = 1;

               $response['eventid'] = $eventid;
               $response['status'] = 1;
               $response['message'] = 'Event created successfully.';
          }
     }

     if($status == 0){
          $response['status'] = 0;
          $response['message'] = 'Event not created.';
     }

     echo json_encode($response);
     exit;
}

// Move event
if($request == 'moveEvent'){

     // POST data
     $eventid = 0; 
     $start_date = ""; $end_date = "";

     if(isset($_POST['eventid']) && is_numeric($_POST['eventid'])){
          $eventid = $_POST['eventid'];
     }
     if(isset($_POST['start_date'])){
          $start_date = $_POST['start_date'];
     }
     if(isset($_POST['end_date'])){
          $end_date = $_POST['end_date'];
     }

     $response = array();
     $status = 0;

     // Check event id
     $sql = "SELECT id FROM events WHERE id=".$eventid;
     $result = mysqli_query($con,$sql);
     if(mysqli_num_rows($result)){
         // Update record
         $sql = "UPDATE events SET start_date='".$start_date."',end_date='".$end_date."' WHERE id=".$eventid;
         if(mysqli_query($con,$sql)){
              $status = 1;

              $response['status'] = 1;
              $response['message'] = 'Event date updated successfully.';
         }
     }

     if($status == 0){
          $response['status'] = 0;
          $response['message'] = 'Event date not updated.';
     }

     echo json_encode($response);
     exit;
}

// Update event
if($request == 'editEvent'){

     // POST data
     $eventid = 0;
     if(isset($_POST['eventid']) && is_numeric($_POST['eventid'])){
          $eventid = $_POST['eventid'];
     }
     if(isset($_POST['title'])){
          $title = $_POST['title'];
     }
     if(isset($_POST['description'])){
          $description = $_POST['description'];
     }

     $response = array();

     if($eventid > 0 && !empty($title) && !empty($description) ){

          // Check event id
          $sql = "SELECT id FROM events WHERE id=".$eventid;
          $result = mysqli_query($con,$sql);
          if(mysqli_num_rows($result)){

               // Update record
               $sql = "UPDATE events SET title='".$title."', description='".$description."' WHERE id=".$eventid;
               if(mysqli_query($con,$sql)){

                    $status = 1;

                    $response['status'] = 1;
                    $response['message'] = 'Event updated successfully.';
               }
          }

     }

     if($status == 0){
          $response['status'] = 0;
          $response['message'] = 'Event not updated.';
     }

     echo json_encode($response);
     exit;
}

// Delete Event
if($request == 'deleteEvent'){

     // POST data
     $eventid = 0;
     if(isset($_POST['eventid']) && is_numeric($_POST['eventid'])){
          $eventid = $_POST['eventid'];
     }

     $response = array();
     $status = 0;

     if($eventid > 0){

          // Check event id
          $sql = "SELECT id FROM events WHERE id=".$eventid;
          $result = mysqli_query($con,$sql);
          if(mysqli_num_rows($result)){

               // Delete record
               $sql = "DELETE FROM events WHERE id=".$eventid;
               if(mysqli_query($con,$sql)){
                     $status = 1;

                     $response['status'] = 1;
                     $response['message'] = 'Event deleted successfully.';
               }
          }

     }

     if($status == 0){
          $response['status'] = 0;
          $response['message'] = 'Event not deleted.';
     }

     echo json_encode($response);
     exit;
}

7. jQuery: Initializing FullCalendar and Managing Events

jQuery script to set up FullCalendar and manage events:

1. Initializing FullCalendar: Initiating FullCalendar within the <div id='calendar'> element. Specify several options for customization, such as:

  • initialDate – By default, FullCalendar shows the current month but you can also specify a date in yyyy-mm-dd format.
  • height – By default, it fits on the whole screen but you change its height using this option. I set it to 600px.
  • selectable – Allow event selection. The default value is true.
  • editable – Allow event drag and drop on a different date. The default value is false.
  • dayMaxEvents – It shows a more button if many events are set on a date. The default value is false.
  • events – Load existing events. Specify the file from where need to load events. Set to fetchevents.php.
  • select – This event trigger when click on a day. Using this to add a new event by displaying a popup box to enter event details.

2. Creating New Events: When a user selects a date, a pop-up alert will appear, allowing them to add an event. This alert includes input fields for the event title and description. Here’s the process:

  • When the confirmation button is clicked, the entered details are captured.
  • AJAX POST request is sent to ajaxfile.php with request: 'addEvent' and event details.
  • Upon successful insertion (response.status == 1), a new event is created using calendar.addEvent().
  • Display a success or error message using the SweetAlert library.

3. Moving Events: When an event is dragged and dropped to a new date, the following steps occur:

  • The event’s new start and end dates are captured.
  • AJAX POST request is sent to ajaxfile.php with request: 'moveEvent' and updated event details.
  • Interaction is synchronous (async: false) to ensure proper handling.

4. Editing and Deleting Events: When an existing event is clicked, an alert appears with options to edit or delete the event. Here’s what happens:

  • The alert displays the event’s title and description in the input fields.
  • If ‘Update’ is confirmed, a new AJAX POST request is sent to ajaxfile.php with request: 'editEvent' and updated event details.
  • Upon success (response.status == 1), all events are refetched using calendar.refetchEvents().
  • If ‘Delete’ is clicked, another AJAX POST request with request: 'deleteEvent' and event ID is sent.
  • On success, the event is removed from the calendar using arg.event.remove().

Make sure to insert this script at the end of the </body> section in your index.php file.

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

     var calendar = new FullCalendar.Calendar(calendarEl, {
         initialDate: '<?= $currentData ?>',
         height: '600px',
         selectable: true,
         editable: true, 
         dayMaxEvents: true, // allow "more" link when too many events 
         events: 'fetchevents.php', // Fetch all events
         select: function(arg) { // Create Event

              // Alert box to add event
              Swal.fire({
                  title: 'Add New Event',
                  showCancelButton: true,
                  confirmButtonText: 'Create',
                  html:
                  '<input id="eventtitle" class="swal2-input" placeholder="Event name" style="width: 84%;" >' +
                  '<textarea id="eventdescription" class="swal2-input" placeholder="Event description" style="width: 84%; height: 100px;"></textarea>',
                  focusConfirm: false,
                  preConfirm: () => {
                       return [
                            document.getElementById('eventtitle').value,
                            document.getElementById('eventdescription').value
                       ]
                  }
              }).then((result) => {

                  if (result.isConfirmed) {

                      var title = result.value[0].trim();
                      var description = result.value[1].trim();
                      var start_date = arg.startStr;
                      var end_date = arg.endStr;

                      if(title != '' && description != ''){

                           // AJAX - Add event
                           $.ajax({
                               url: 'ajaxfile.php',
                               type: 'post',
                               data: {request: 'addEvent',title: title,description: description,start_date: start_date,end_date: end_date},
                               dataType: 'json',
                               success: function(response){
                                    
                                    if(response.status == 1){

                                         // Add event
                                         calendar.addEvent({
                                              eventid: response.eventid,
                                              title: title,
                                              description: description,
                                              start: arg.start,
                                              end: arg.end,
                                              allDay: arg.allDay
                                         })

                                         // Alert message 
                                         Swal.fire(response.message,'','success'); 
                                    }else{
                                         // Alert message 
                                         Swal.fire(response.message,'','error'); 
                                    }

                               }
                           });
                      }

                  }
              })

              calendar.unselect()
         },
         eventDrop: function (event, delta) { // Move event

              // Event details
              var eventid = event.event.extendedProps.eventid;
              var newStart_date = event.event.startStr;
              var newEnd_date = event.event.endStr;

              // AJAX request
              $.ajax({
                  url: 'ajaxfile.php',
                  type: 'post',
                  data: {request: 'moveEvent',eventid: eventid,start_date: newStart_date, end_date: newEnd_date},
                  dataType: 'json',
                  async: false,
                  success: function(response){

                       console.log(response);

                  }
              });

         },
         eventClick: function(arg) { // Edit/Delete event

              // Event details
              var eventid = arg.event._def.extendedProps.eventid;
              var description = arg.event._def.extendedProps.description;
              var title = arg.event._def.title;

              // Alert box to edit and delete event
              Swal.fire({
                   title: 'Edit Event',
                   showDenyButton: true,
                   showCancelButton: true,
                   confirmButtonText: 'Update',
                   denyButtonText: 'Delete',
                   html:
                   '<input id="eventtitle" class="swal2-input" placeholder="Event name" style="width: 84%;" value="'+ title +'" >' +
                   '<textarea id="eventdescription" class="swal2-input" placeholder="Event description" style="width: 84%; height: 100px;">' + description + '</textarea>',
                   focusConfirm: false,
                   preConfirm: () => {
                        return [
                            document.getElementById('eventtitle').value,
                            document.getElementById('eventdescription').value
                        ]
                   }
              }).then((result) => {

                   if (result.isConfirmed) { // Update

                        var newTitle = result.value[0].trim();
                        var newDescription = result.value[1].trim();

                        if(newTitle != ''){

                             // AJAX - Edit event
                             $.ajax({
                                 url: 'ajaxfile.php',
                                 type: 'post',
                                 data: {request: 'editEvent',eventid: eventid,title: newTitle, description: newDescription},
                                 dataType: 'json',
                                 async: false,
                                 success: function(response){

                                     if(response.status == 1){

                                         // Refetch all events
                                         calendar.refetchEvents();

                                         // Alert message
                                         Swal.fire(response.message, '', 'success');
                                     }else{
                                         // Alert message
                                         Swal.fire(response.message, '', 'error');
                                     }

                                 }
                             }); 
                        }

                   } else if (result.isDenied) { // Delete

                        // AJAX - Delete Event
                        $.ajax({
                             url: 'ajaxfile.php',
                             type: 'post',
                             data: {request: 'deleteEvent',eventid: eventid},
                             dataType: 'json',
                             async: false,
                             success: function(response){

                                 if(response.status == 1){
                                       arg.event.remove();

                                       // Alert message
                                       Swal.fire(response.message, '', 'success');
                                 }else{
                                       // Alert message
                                       Swal.fire(response.message, '', 'error');
                                 }

                             }
                        }); 
                   }
              })

         }
     });

     calendar.render();
});

8. Demo

View Demo


9. Conclusion

In the example, I have used sweetAlert plugin to display a popup box to enter and display details. You can also use any other plugin with which you are compatible.

You have to create a separate file to fetch all events. It is not possible to manage it from a single file to handle all Fullcalendar actions – update/delete. It will cause problems during refetch events after editing an event.

If you found this tutorial helpful then don't forget to share.

Leave a Comment