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.
Contents
- Table structure
- Database Configuration
- Download and Include
- HTML
- PHP File – Fetch all events
- PHP File – Handle AJAX requests
- jQuery
- Demo
- Conclusion
1. Table structure
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. Database Configuration
Create a config.php
for database configuration.
Completed Code
<?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
- Download Fullcalendar and sweetAlert libraries.
- Also included a jQuery library to send AJAX requests.
<!-- 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
Create index.php
file.
Stored current date in $currentData
, this is used to set the initial date of FullCalendar. Create <div id='calendar'>
to initialize FullCalendar()
.
Completed Code
<?php $currentData = date('Y-m-d'); ?> <!-- Calendar Container --> <div id='calendar-container'> <div id='calendar'></div> </div>
5. PHP File – Fetch all events
Create fetchevents.php
file to load all created events list in FullCalendar.
Fetch all records from the events
table and assign it to $eventsList
. Loop on the $eventsList
and initialize $response
Array with eventid, title, description, start, and end date.
Return $response
in JSON format.
Completed Code
<?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. PHP File – Handle AJAX requests
Create ajaxfile.php
file.
From here handle 4 requests –
- addEvent – Add new event.
- moveEvent – Update event date.
- editEvent – Update event details.
- deleteEvent – Delete event.
$request == ‘addEvent’ –
Read POST data and assign it to the variables. If variable values are not empty then insert a new record in the events
table.
Store last insert id in $eventid
variable and 1 to $status
. Initialize $response
Array with eventid, status, and message keys. Assign $eventid
to eventid
key, 1 to status
, and success message to message
key.
If a record is not inserted then store 0 to status
and error message to message
key in $response
Array.
Return $response
Array in JSON format.
$request == ‘moveEvent’ –
Read POST new dates and update event id. If $eventid > 0
and $start_date
and $end_date
is not empty then check if $eventid
exists in the events
table or not. If exists then update start_date
and end_date
fields and assign 1 to $status
. In $response
Array store 1 to status
key and success message to message
key.
If a record is not updated then store 0 to status
key and error message to message
key.
Return $response
Array in JSON format.
$request == ‘editEvent’ –
Read POST event details and update event id. If $eventid > 0
and $title
and $description
is not empty then check if $eventid
exists in the events
table or not. If exists then update title
and description
fields value in the events
table with new POST value.
Assign 1 to $status
and store 1 to status
key and success message to message
key in $response
Array.
If a record is not updated then store 0 to status
key and error message to message
key.
Return $response
Array in JSON format.
$request == ‘deleteEvent’ –
Read POST event id and check if it is > 0
or not. If it is then check the record in the events
table exists with $eventid
id.
Delete the record if exists and assign 1 to $status
. In the $response
Array store 1 to status
key and success message to message
key.
If not deleted then assign 0 to status
key and error message to message
key in the $response
Array.
Return $response
Array in JSON format.
Completed Code
<?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
Initaiilze FullCalendar on <div id='calendar'>
.
Here, I specified the following options –
- initialDate – By default FullCalendar show the current month but you can also specify a date in
yyyy-mm-dd
format. - height – By default, it is fit 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 show 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.
Display sweetAlert confirm box that has a textbox to enter the event name and textarea to enter the description.
If confirm button gets clicked then read entered values and event start and end date. Send AJAX POST request to ajaxfile.php
, pass request: 'addEvent'
and event details. On successful callback check response status. If it is 1 means a record successfully inserted in the MySQL database, using calendar.addEvent();
create an event.
Here, I also set eventid
, this is use to update/delete a record.
Display alert message according to the response.status
.
- eventDrop – This event trigger when drag & drop an item in the calendar. Using this update the event date.
Read selected event – eventid, new start and end date. Send AJAX POST request to ajaxfile.php
, pass request: 'moveEvent'
, update event id, and dates.
- eventClick – This event trigger when clicked on the existing event. Using this update/delete a event.
Read eventid, title and description. Create sweetAlert confirm box that has 3 buttons – Update, Delete, and Cancel. Set the title and description values in the textbox and textarea.
Edit Event
If result.isConfirmed
is true
means update button is clicked. Read entered values and send AJAX POST request to ajaxfile.php
, pass request: 'editEvent'
, update event id, new title and description. On successful callback, if response.status == 1
then refetch all events by calling – calendar.refetchEvents();
and display the response message.
Delete Event
If result.isDenied
is true
means delete button is clicked. Send AJAX POST request to ajaxfile.php
, pass request: 'deleteEvent'
, delete event id. On successful callback if response.status == 1
then remove the event from calendar by calling – arg.event.remove();
and display the response message.
NOTE – I added the script to the
index.php
file at the end of</body>
.
Completed Code
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
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.