En esta ocasión se crea un proyecto en Laravel 11 para implementar el CRUD (Crear, Leer, Actualizar y Borrar) necesario para trabajar con el plugins javascript de FullCalendar.
¿Que necesitamos?
Una vez que ya tengas tu proyecto laravel 11 creado y abierto en tu editor de codigo favorito. Pongamos manos a la obra
Paso 1. Migration
Creamos una nueva migración donde se declara la tabla «events», en la misma se registraran todos los eventos del fullcalendar.
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('events', function (Blueprint $table) { $table->id(); $table->string('title'); $table->date('start'); $table->date('end'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('events'); } };
Se realiza la migración con el comando:
php artisan migrate:refresh
Paso 2. Model
A continuación se crea el modelo «Event»
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Event extends Model { use HasFactory; protected $fillable = [ 'title', 'start', 'end' ]; }
Paso 3. Services
Se crea una clase Service con el nombre «FullCalendarService.php», en el mismo se declaran las funciones necesarias para el CRUD.
<?php namespace App\Services; use Illuminate\Http\Request; use App\Models\Event; class FullCalendarService { public function events(Request $request) { $data = Event::whereDate('start', '>=', $request->start) ->whereDate('end', '<=', $request->end) ->get(['id', 'title', 'start', 'end']); return response()->json($data); } public function add(Request $request){ $event = Event::create([ 'title' => $request->title, 'start' => $request->start, 'end' => $request->end, ]); return response()->json($event); } public function update(Request $request){ $event = Event::find($request->id)->update([ 'title' => $request->title, 'start' => $request->start, 'end' => $request->end, ]); return response()->json($event); } public function destroy($id){ $event = Event::find($id)->delete(); return response()->json($event); } }
Paso 4. Controller
Se requiere una clase controller bajo el nombre de «FullCalendarController.php», en el mismo se inyectara el Service creado en el paso 3 y se declaran las funciones respectivas para el CRUD.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Services\FullCalendarService; use Illuminate\Http\JsonResponse; class FullCalendarController extends Controller { protected $fullCalendarService; public function __construct(FullCalendarService $fullCalendarService) { $this->fullCalendarService = $fullCalendarService; } public function index() { return view('fullcalendar.index'); } public function events(Request $request) { return $this->fullCalendarService->events($request); } public function add(Request $request): JsonResponse { return $this->fullCalendarService->add($request); } public function update(Request $request): JsonResponse { return $this->fullCalendarService->update($request); } public function destroy(Request $request) { return $this->fullCalendarService->destroy($request->id); } }
Paso 5. View
Ya finalizando se crea una vista index.blade.php en la ruta «views/fullcalendar/».
<!DOCTYPE html> <html> <head> <title>CRUD Fullcalendar - Laravel 11 (https://www.jc-mouse.net/)</title> <meta name="csrf-token" content="{{ csrf_token() }}"> <link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'> <link href='https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css' rel='stylesheet'> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js"></script> <script src='https://cdn.jsdelivr.net/npm/@fullcalendar/core@6.1.15/locales-all.global.min.js'></script> </head> <body> <div class="container"> <div class="card"> <div class="card-body"> <div id='calendar'></div> </div> </div> </div> <script type="text/javascript"> document.addEventListener('DOMContentLoaded', function() { var calendarEl = document.getElementById('calendar'); var calendar = new FullCalendar.Calendar(calendarEl, { headerToolbar: { left: 'prevYear,prev,next,nextYear today' , center: 'title' , right: 'dayGridMonth,dayGridWeek,dayGridDay' } , navLinks: true , editable: true , displayEventTime: false , selectable: true , locale: 'es' , events: "{{ route('fullcalendar.events') }}", /** ------------------------------------------------------------- * creacion de eventos */ dateClick: function(info) { var title = prompt('Nuevo evento:'); if (title) { var start = moment(info.dateStr).format('Y-MM-DD'); var end = moment(info.dateStr).format('Y-MM-DD'); $.ajax({ url: "{{ route('fullcalendar.events.add') }}" , data: { _token: $('meta[name="csrf-token"]').attr('content') , title: title , start: start , end: end } , type: "POST" , success: function(data) { calendar.addEvent({ id: data.id , title: title , start: end , allDay: false }); calendar.render(); } }); } }, /** ------------------------------------------------------------- * Eliminación de eventos */ eventClick: function(info) { var deleteMsg = confirm("¿Realmente quieres eliminar este evento?"); if (deleteMsg) { $.ajax({ type: "DELETE" , url: "{{ route('fullcalendar.events.destroy') }}" , data: { _token: $('meta[name="csrf-token"]').attr('content') , id: info.event.id , } , success: function(response) { info.event.remove(); } }); } }, /** ------------------------------------------------------------- * Actualización de eventos */ eventDrop: function(info) { var start = moment(info.event.start).format('Y-MM-DD'); var end = moment(info.event.start).format('Y-MM-DD'); $.ajax({ url: "{{ route('fullcalendar.events.update') }}" , data: { _token: $('meta[name="csrf-token"]').attr('content') , title: info.event.title , start: start , end: end , id: info.event.id } , type: "PUT" , success: function(response) { console.log(response); } }); }, }); calendar.render(); }); </script> </body> </html>
Paso 6. Routes
Finalmente declaramos rutas necesarias para el CRUD en el archivo routes.php.
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\FullCalendarController; Route::controller(FullCalendarController::class)->group(function(){ Route::get('fullcalendar', 'index'); Route::get('events', 'events')->name('fullcalendar.events'); Route::post('events/add', 'add')->name('fullcalendar.events.add'); Route::put('events/update', 'update')->name('fullcalendar.events.update'); Route::delete('events/destroy', 'destroy')->name('fullcalendar.events.destroy'); });
Y ya solo nos queda abrir el proyecto desde el navegador: http://laravel-fullcalendar.test/fullcalendar y tenemos:
Videito en TikTok 🙂
Enjoy!!!
«Las palabras que elegimos dan forma a nuestra realidad. La Fuente Educada (Polite Type) es una fuente de código abierto[...]
En este post, escribiremos un sencillo plugin para wordpress el cual consistirá en reemplazar palabras en los comentario[...]
Quinta parte de la serie de tutoriales «Creación de un blog siguiendo el patrón MVC (Modelo, Vista y Controlador)«. En e[...]
Tercera parte del tutorial [Crea tu blog con el patrón MVC y php] En este post trabajaremos en el Theme del blog, agrega[...]
En este post realizaremos un pequeño ejemplo de validación de archivos XML utilizando el esquema XSD y el lenguaje PHP ([...]
Por lo general se usan transacciones a nivel base de datos y posteriormente se llaman estos a través de procedimientos a[...]