[caption id="attachment_2980" align="aligncenter" width="2048"]
FullCalendar con PHP[/caption]
En este tutorial, aprenderás a implementar un calendario interactivo utilizando FullCalendar, un popular plugin de JavaScript que permite gestionar eventos de manera sencilla y efectiva. Utilizaremos PHP y MySQL para manejar los datos del calendario, así como Bootstrap 5 y jQuery para crear una interfaz de usuario atractiva y funcional. A lo largo del tutorial, abordaremos cómo agregar, editar y eliminar eventos en el calendario, garantizando que tengas una comprensión completa del proceso.
Requisitos Previos
Antes de comenzar, asegúrate de tener instalado lo siguiente:
- Servidor web con PHP (XAMPP, WAMP, etc.)
- Base de datos MySQL
- Conocimientos básicos de PHP, MySQL, HTML, CSS y JavaScript.
Estructura del Proyecto
Crea una carpeta para tu proyecto y dentro de ella, crea la siguiente estructura de archivos:
/tu-proyecto ├── index.php ├── fetch_events.php ├── add_event.php ├── update_event.php ├── delete_event.php ├── db_connection.php
Configuración de la Base de Datos
- Accede a tu administrador de base de datos (phpMyAdmin, por ejemplo).
- Crea una base de datos llamada
test_calendario. - Crea una tabla llamada
eventoscon la siguiente estructura:
CREATE TABLE eventos (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
start DATETIME NOT NULL,
end DATETIME NOT NULL
);
Creación de Archivos PHP
index.php
Este archivo contendrá el código HTML y JavaScript necesario para cargar y manejar el calendario.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calendario con FullCalendar, PHP y MySQL</title>
<!-- FullCalendar CSS -->
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.css" rel="stylesheet">
<!-- Bootstrap CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1 class="text-center">Calendario de Eventos</h1>
<div id="calendar"></div>
</div>
<!-- Modal para Crear/Editar Evento -->
<div class="modal fade" id="eventModal" tabindex="-1" aria-labelledby="eventModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form id="eventForm">
<div class="modal-header">
<h5 class="modal-title" id="eventModalLabel">Agregar Evento</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="title" class="form-label">Título del Evento</label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<div class="mb-3">
<label for="start" class="form-label">Fecha de Inicio</label>
<input type="date" class="form-control" id="start" name="start" required>
</div>
<div class="mb-3">
<label for="end" class="form-label">Fecha de Fin</label>
<input type="date" class="form-control" id="end" name="end">
</div>
<input type="hidden" id="eventId" name="eventId">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Guardar</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" id="deleteEventBtn" class="btn btn-danger" style="display: none;">Eliminar Evento</button>
</div>
</form>
</div>
</div>
</div>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
<!-- FullCalendar JS -->
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/locales/es.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const calendarEl = document.getElementById('calendar');
const calendar = new FullCalendar.Calendar(calendarEl, {
locale: 'es',
initialView: 'dayGridMonth',
editable: true,
events: 'fetch_events.php',
eventClick: function(info) {
// Editar evento al hacer clic
$('#eventModal').modal('show');
$('#title').val(info.event.title);
$('#start').val(info.event.startStr);
$('#end').val(info.event.endStr);
$('#eventId').val(info.event.id);
$('#eventModalLabel').text('Editar Evento');
$('#deleteEventBtn').show(); // Mostrar botón de eliminar
},
dateClick: function(info) {
// Crear nuevo evento al hacer clic en una fecha
$('#eventModal').modal('show');
$('#eventForm')[0].reset();
$('#start').val(info.dateStr);
$('#end').val('');
$('#eventId').val('');
$('#eventModalLabel').text('Agregar Evento');
$('#deleteEventBtn').hide(); // Ocultar botón de eliminar
}
});
calendar.render();
// Guardar evento (Agregar o Editar)
$('#eventForm').on('submit', function(e) {
e.preventDefault();
const eventData = {
title: $('#title').val(),
start: $('#start').val(),
end: $('#end').val(),
id: $('#eventId').val()
};
$.ajax({
url: eventData.id ? 'update_event.php' : 'add_event.php',
type: 'POST',
dataType: 'json',
data: eventData,
success: function(response) {
$('#eventModal').modal('hide');
calendar.refetchEvents(); // Recargar eventos
if (response && response.message) {
alert(response.message);
} else {
alert("Error: respuesta no válida del servidor");
}
},
error: function() {
alert("Error al guardar el evento.");
}
});
});
// Eliminar evento
$('#deleteEventBtn').on('click', function() {
const eventId = $('#eventId').val();
if (eventId) {
$.ajax({
url: 'delete_event.php',
type: 'POST',
dataType: 'json',
data: { id: eventId },
success: function(response) {
$('#eventModal').modal('hide');
calendar.refetchEvents(); // Recargar eventos
alert(response.message); // Mostrar mensaje de éxito o error
},
error: function() {
alert("Error al eliminar el evento.");
}
});
}
});
});
</script>
</body>
</html>
fetch_events.php
Este archivo se encarga de recuperar los eventos de la base de datos y devolverlos en formato JSON.
<?php // Incluir archivo de conexión include 'db_connection.php';$sql = "SELECT id, title, start, end FROM eventos"; $result = $conexion->query($sql);
$events = []; while ($row = $result->fetch_assoc()) { $events[] = $row; }
header('Content-Type: application/json'); echo json_encode($events); ?>
add_event.php
Este archivo permite agregar nuevos eventos a la base de datos.
<?php // Incluir archivo de conexión include 'db_connection.php';$title = $_POST['title']; $start = $_POST['start']; $end = $_POST['end'] ?: $start;
$sql = "INSERT INTO eventos (title, start, end) VALUES (?, ?, ?)"; $stmt = $conexion->prepare($sql); $stmt->bind_param("sss", $title, $start, $end); $stmt->execute();
// Verificar si se insertó el evento if ($stmt->affected_rows > 0) { $response = ['message' => 'Evento agregado exitosamente']; } else { $response = ['message' => 'Error al agregar el evento']; }
// Respuesta en JSON header('Content-Type: application/json'); echo json_encode($response); ?>
update_event.php
Este archivo permite actualizar los eventos existentes.
<?php // Incluir archivo de conexión include 'db_connection.php';$id = $_POST['id']; $title = $_POST['title']; $start = $_POST['start']; $end = $_POST['end'] ?: $start;
$sql = "UPDATE eventos SET title = ?, start = ?, end = ? WHERE id = ?"; $stmt = $conexion->prepare($sql); $stmt->bind_param("sssi", $title, $start, $end, $id); $stmt->execute();
// Verificar si se actualizó el evento if ($stmt->affected_rows > 0) { $response = ['message' => 'Evento actualizado exitosamente']; } else { $response = ['message' => 'Error al actualizar el evento']; }
// Respuesta en JSON header('Content-Type: application/json'); echo json_encode($response); ?>
delete_event.php
Este archivo permite eliminar eventos de la base de datos.
<?php // Incluir archivo de conexión include 'db_connection.php';$id = $_POST['id'];
$sql = "DELETE FROM eventos WHERE id = ?"; $stmt = $conexion->prepare($sql); $stmt->bind_param("i", $id); $stmt->execute();
if ($stmt->affected_rows > 0) { $response = ['message' => 'Evento eliminado exitosamente']; } else { $response = ['message' => 'Error al eliminar el evento']; }
header('Content-Type: application/json'); echo json_encode($response); ?>
db_connection.php
Este archivo maneja la conexión a la base de datos.
<?php // db_connection.php$host = "localhost"; $username = "root"; $password = ""; $dbname = "test_calendario";
// Crear la conexión $conexion = new mysqli($host, $username, $password, $dbname);
// Verificar la conexión if ($conexion->connect_error) { die("Conexión fallida: " . $conexion->connect_error); }
// Establecer la codificación de caracteres a UTF-8 $conexion->set_charset("utf8");
?>
Integración de FullCalendar
En este capítulo, hemos integrado el plugin FullCalendar y lo hemos configurado para cargar eventos desde la base de datos. También hemos creado un modal para agregar y editar eventos.
Agregar Funcionalidad para Editar y Eliminar Eventos
En este capítulo, hemos implementado la lógica para editar y eliminar eventos a través de AJAX, haciendo que nuestra aplicación sea más interactiva y dinámica.
Conclusiones
A lo largo de este tutorial, hemos aprendido a crear un calendario interactivo utilizando FullCalendar, PHP y MySQL. Este conocimiento puede ser extendido y adaptado para desarrollar aplicaciones más complejas que requieran gestión de eventos.
Cabe mencionar que previamente habíamos publicado un tutorial similar en FullCalendar con PHP y MySQL. Sin embargo, ya ha pasado bastante tiempo desde entonces; si gustas, puedes echarle un vistazo. Dado el tiempo transcurrido y la aceptación que tuvo en su momento, decidimos realizar una actualización de ese contenido, adaptándolo a las tecnologías y buenas prácticas actuales.
Comentarios