Overview
En este tutorial, aprenderás a usar MongoDB en una aplicación Laravel creando un sistema sencillo de recordatorios de tareas. La aplicación te permite crear, leer, actualizar y eliminar tareas. Además, envía recordatorios por correo electrónico para las próximas tareas según una hora programada.
Requisitos previos
Antes de comenzar con este tutorial, asegúrese de tener los siguientes componentes instalados en su entorno de desarrollo:
También debes configurar un clúster de MongoDB Atlas. Para aprender a configurar un clúster, consulta la guía de inicio rápido.
Pasos
Instala el paquete de MongoDB Laravel.
Para utilizar MongoDB en tu aplicación, debes instalar el paquete Laravel MongoDB y configurarlo en el config/database.php .env.
Instala el paquete utilizando el siguiente comando:
composer require mongodb/laravel-mongodb
Tip
Si aparece un error al ejecutar el comando anterior, asegúrese de que la extensión PHP de MongoDB esté instalada. Para aprender cómo instalar, consulta el paso Instalar la extensión PHP de MongoDB en la guía Primeros pasos.
Configure la conexión con la base de datos.
Una vez finalizada la instalación del paquete de MongoDB de Laravel, agregue la conexión de la base de datos de MongoDB al archivo config/database.php para completar la configuración. Agrega la siguiente configuración de MongoDB al arreglo connections que contiene configuraciones para otros tipos de bases de datos:
return [ 'connections' => [ 'mongodb' => [ 'driver' => 'mongodb', 'dsn' => env('MONGODB_URI'), 'database' => 'task_reminder', ], // Other connections here ], ];
Tu aplicación obtiene el valor de dsn del archivo .env. Navegue hasta su archivo .env. Luego, crea un valor para MONGODB_URI y configúralo con el valor de tu cadena de conexión MongoDB.
Tip
Para obtener tu cadena de conexión de MongoDB, navega a tu clúster en MongoDB Atlas. Haz clic en el Connect botón y hacer clic en el Drivers debajo de Connect your application. Selecciona "PHP" en el menú de selección Driver. Copie la cadena de conexión de la ventana de diálogo. Para obtener pasos detallados sobre cómo obtener su cadena de conexión, consulte crear-una-cadena-de-conexión.
En el archivo .env, establezca el valor DB_CONNECTION en mongodb para que sea la conexión predeterminada de su aplicación. Edite el valor SESSION_DRIVER y configúrelo en mongodb, como se muestra en el siguiente código:
MONGODB_URI=mongodb+srv://YOUR_MONGODB_CONNECTION_STRING DB_CONNECTION=mongodb // Other DB_ values here ... SESSION_DRIVER=mongodb
Configurar la autenticación con Laravel Breeze.
Después de instalar y configurar su aplicación para trabajar con MongoDB, configure la autenticación. Laravel simplifica la implementación de la autenticación al proporcionar paquetes como Laravel Breeze, Laravel Fortify y Laravel Jetstream. Este tutorial utiliza Laravel Breeze para la autenticación.
Instala Laravel Breeze utilizando Composer:
composer require laravel/breeze --dev
Una vez completada la instalación, ejecute los siguientes comandos:
php artisan key:generate php artisan breeze:install php artisan migrate php artisan db:seed npm install npm run dev
Se le pedirá que elija su pila y paquete de pruebas preferidos. Para este tutorial, seleccione la primera opción, Blade con Alpine.
┌ Which Breeze stack would you like to install? ───────────────┐ │ > ● Blade with Alpine │ │ ○ Livewire (Volt Class API) with Alpine │ │ ○ Livewire (Volt Functional API) with Alpine │ │ ○ React with Inertia │ │ ○ Vue with Inertia │ │ ○ API only │ └──────────────────────────────────────────────────────────────┘
Este comando añade vistas de autenticación, rutas, controladores y otros recursos relacionados a tu aplicación.
Configura el modelo de usuario y la autenticación para MongoDB.
Laravel Breeze crea un modelo de usuario predeterminado para bases de datos SQL. Debe actualizarlo para que funcione con MongoDB y solucionar problemas de compatibilidad con limitaciones de velocidad.
Abre app/Models/User.php y reemplaza su contenido con lo siguiente:
namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Notifications\Notifiable; use MongoDB\Laravel\Auth\User as MongoUser; class User extends MongoUser { use HasFactory, Notifiable; protected $connection = 'mongodb'; protected $collection = 'users'; /** * The attributes that are mass assignable. * * @var array<int, string> */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for serialization. * * @var array<int, string> */ protected $hidden = [ 'password', 'remember_token', ]; /** * Get the attributes to cast. * * @return array<string, string> */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; } }
Sirva el proyecto y pruebe la conexión MongoDB.
Sirva el proyecto usando el servidor integrado de Laravel y confirme que todo funciona correctamente. En el directorio del proyecto de Laravel, ejecute el siguiente comando:
php artisan serve
El proyecto se ejecuta en 127.0.0.1:8000. Si el puerto 8000 ya está en uso, Laravel cambia a un nuevo puerto disponible y lo imprime en la terminal.
Para probar el sistema de autenticación, selecciona el botón Register en tu aplicación y crea una nueva cuenta de usuario. Esto almacena el usuario en tu base de datos MongoDB y te permite iniciar sesión con esas credenciales. Para este tutorial, puedes establecer el nombre de usuario en test@example.com y la contraseña en password.
Para verificar que el paquete Laravel MongoDB esté configurado correctamente, crea una ruta para hacer ping a tu clúster de MongoDB. Agrega lo siguiente a routes/web.php:
Route::get('/ping', function (Request $request) { $connection = DB::connection('mongodb'); try { $connection->command(['ping' => 1]); $msg = 'MongoDB is accessible!'; } catch (\MongoDB\Driver\Exception\ConnectionException $e) { $msg = 'You are not connected to MongoDB. Error: ' . $e->getMessage(); } return ['msg' => $msg]; });
Visita esta ruta en tu navegador. Con la configuración correcta, verás el mensaje "¡MongoDB está accesible!" en tu navegador.
Crear el modelo y el controlador de la tarea.
Crea el modelo y el controlador para la funcionalidad de programación de tareas usando el siguiente comando:
php artisan make:model Task --resource --controller
Este comando crea el modelo Task en el directorio app/Models y el TaskController en el directorio app/Http/Controllers con métodos de recursos.
Cree una ruta para el TaskController yendo a routes/web.php y agregando el siguiente código:
use App\Http\Controllers\TaskController; // Other route definitions... Route::resource('tasks', TaskController::class)->middleware('auth');
Configura el modelo de Tarea.
Navegue a app/Models/Task.php y reemplace el contenido del archivo con el siguiente código:
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Task extends Model { protected $connection = 'mongodb'; protected $table = 'tasks'; protected $fillable = [ 'title', 'description', 'due_date', 'email', 'reminder_time', 'last_notification_date' ]; }
Este código crea el modelo de tarea con las siguientes especificaciones:
La instrucción
use MongoDB\Laravel\Eloquent\Modelposterior al namespace es específica de los modelos de MongoDB. Sobrescribe las funcionalidades de Eloquent implementadas con SQL utilizando queries de MongoDB.La propiedad
protected $table = 'tasks'es opcional. Especifica el nombre de la colección MongoDB utilizada para almacenar los documentos de este modelo.La propiedad
protected $fillableespecifica las propiedades que se pueden asignar en masa.
Tip
Una de las características únicas de MongoDB es que no requiere migraciones como las bases de datos relacionales. Puedes añadir nuevos campos directamente a tus documentos sin actualizar el modelo ni crear migraciones. Esta función es útil para gestionar datos dinámicos.
Crea la lógica de TaskController.
Navega a app/Http/Controllers/TaskController.php y actualiza el contenido con el siguiente código:
namespace App\Http\Controllers; use App\Models\Task; use Carbon\Carbon; use Illuminate\Http\Request; class TaskController extends Controller { /** * Displays a listing of the resource. */ public function index() { $tasks = Task::where('email', auth()->user()->email)->get(); return view('tasks.index', compact('tasks')); } /** * Shows the form for creating a new resource. */ public function create() { return view('tasks.create'); } /** * Stores a newly created resource in storage. */ public function store(Request $request) { $data = $request->validate([ 'title' => 'required|string|max:255', 'description' => 'nullable|string', 'due_date' => 'required|date', 'reminder_time' => 'required|date', ]); $data['due_date'] = Carbon::parse($request->due_date); $data['reminder_time'] = Carbon::parse($request->reminder_time); $data['email'] = auth()->user()->email; $data['last_notification_date'] = null; Task::create($data); return redirect()->route('tasks.index')->with('success', 'Task created successfully.'); } /** * Displays the specified resource. */ public function show(string $id) { // } /** * Shows the form for editing the specified resource. */ public function edit(string $id) { $tasks = Task::where('id', $id)->get(); return view('tasks.edit', ['tasks' => $tasks]); } /** * Updates the specified resource in storage. */ public function update(Request $request, string $id) { $data = $request->validate([ 'title' => 'required|string|max:255', 'description' => 'nullable|string', 'due_date' => 'required|date', 'reminder_time' => 'required|date', ]); $task = Task::findOrFail($id); $data['due_date'] = Carbon::parse($request->due_date)->format('Y-m-d H:i:s'); $data['reminder_time'] = Carbon::parse($request->reminder_time)->format('Y-m-d H:i:s'); $task->update($data); return redirect()->route('tasks.index')->with('success', 'Task updated successfully.'); } /** * Removes the specified resource from storage. */ public function destroy(string $id) { $task = Task::findOrFail($id); $task->delete(); return redirect()->route('tasks.index')->with('success', 'Task deleted successfully.'); } }
La clase TaskController contiene el código que gestiona las operaciones CRUD del modelo de tareas:
El método
index()recupera todas las tareas que pertenecen al usuario que inició sesión y las envía al archivoindex.blade.phppara su visualización.El método
create()devuelve la vista del formulario para crear una nueva tarea.El método
store()valida la entrada, asigna el correo electrónico del usuario que ha iniciado sesión a la tarea y la guarda en la base de datos.El método
edit()recupera la tarea específica que se va a editar y la muestra en un formulario de edición.El método
update()guarda la tarea editada en la colección de tareas de MongoDB.El método
destroy()elimina una tarea específica.
Cada operación redirige de nuevo a la lista de tareas con un mensaje de éxito para la retroalimentación del usuario.
Crea archivos de vista para el programador de tareas.
En el directorio resources/views, crea una carpeta llamada tasks y crea los siguientes archivos en ella:
create.blade.phpedit.blade.phpindex.blade.php
Ir a resources/views/tasks/create.blade.php y agregar este contenido:
1 <x-app-layout> 2 <x-slot name="header"> 3 <h2 class="font-semibold text-xl text-gray-800 leading-tight"> 4 {{ __('Tasks') }} 5 </h2> 6 </x-slot> 7 8 <div class="py-12"> 9 <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> 10 <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg"> 11 <div class="container mx-auto p-4"> 12 <h2 class="text-2xl font-bold mb-4">Create New Task</h2> 13 14 <form action="{{ route('tasks.store') }}" method="POST"> 15 @csrf 16 17 <div class="mb-4"> 18 <label for="title" class="block text-gray-700">Title:</label> 19 <input type="text" 20 name="title" 21 id="title" 22 required 23 class="border border-gray-300 p-2 w-full" 24 value="{{ old('title') }}"> 25 @error('title') 26 <p class="text-red-500">{{ $message }}</p> 27 @enderror 28 </div> 29 30 <div class="mb-4"> 31 <label for="description" class="block text-gray-700">Description:</label> 32 <textarea name="description" 33 id="description" 34 class="border border-gray-300 p-2 w-full">{{ old('description') }}</textarea> 35 </div> 36 37 <div class="mb-4"> 38 <label for="due_date" class="block text-gray-700">Due Date:</label> 39 <input type="date" 40 name="due_date" 41 id="due_date" 42 required 43 class="border border-gray-300 p-2 w-full" 44 value="{{ old('due_date') }}"> 45 @error('due_date') 46 <p class="text-red-500">{{ $message }}</p> 47 @enderror 48 </div> 49 50 <div class="mb-4"> 51 <label for="reminder_time" class="block text-gray-700">Reminder Time:</label> 52 <input type="datetime-local" 53 name="reminder_time" 54 id="reminder_time" 55 class="border border-gray-300 p-2 w-full" 56 value="{{ old('reminder_time') }}"> 57 </div> 58 59 <button type="submit" 60 class="bg-green-600 text-white p-2 border rounded"> 61 Create Task 62 </button> 63 </form> 64 </div> 65 </div> 66 </div> 67 </div> 68 </x-app-layout>
El formulario contiene campos de texto para title y description, así como campos de fecha y hora para due date y reminder time.
Ir a resources/views/tasks/edit.blade.php y agregar este contenido:
1 <x-app-layout> 2 <x-slot name="header"> 3 <h2 class="font-semibold text-xl text-gray-800 leading-tight"> 4 {{ __('Edit Task') }} 5 </h2> 6 </x-slot> 7 8 <div class="py-12"> 9 <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> 10 <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg"> 11 <div class="p-6 text-gray-900"> 12 @foreach($tasks as $task) 13 <form action="{{ route('tasks.update', $task->id) }}" method="POST"> 14 @csrf 15 @method('PUT') 16 17 <div class="mb-4"> 18 <label for="title" class="block text-gray-700">Title:</label> 19 <input type="text" 20 name="title" 21 id="title" 22 required 23 class="border border-gray-300 p-2 w-full" 24 value="{{ old('title', $task->title) }}"> 25 @error('title') 26 <p class="text-red-500">{{ $message }}</p> 27 @enderror 28 </div> 29 30 <div class="mb-4"> 31 <label for="description" class="block text-gray-700">Description:</label> 32 <textarea name="description" 33 id="description" 34 class="border border-gray-300 p-2 w-full">{{ old('description', $task->description) }}</textarea> 35 </div> 36 37 <div class="mb-4"> 38 <label for="due_date" class="block text-gray-700">Due Date:</label> 39 <input type="date" 40 name="due_date" 41 id="due_date" 42 required 43 class="border border-gray-300 p-2 w-full" 44 value="{{ old('due_date', $task->due_date) }}"> 45 @error('due_date') 46 <p class="text-red-500">{{ $message }}</p> 47 @enderror 48 </div> 49 50 <div class="mb-4"> 51 <label for="reminder_time" class="block text-gray-700">Reminder Time:</label> 52 <input type="datetime-local" 53 name="reminder_time" 54 id="reminder_time" 55 class="border border-gray-300 p-2 w-full" 56 value="{{ old('reminder_time', $task->reminder_time) }}"> 57 </div> 58 59 <button type="submit" 60 class="bg-blue-500 text-white p-2 rounded"> 61 Update Task 62 </button> 63 </form> 64 @endforeach 65 </div> 66 </div> 67 </div> 68 </div> 69 </x-app-layout>
El formulario de edición contiene los mismos campos de entrada que el formulario de creación y se carga con los datos de la tarea que se está editando actualmente.
Ir a resources/views/tasks/index.blade.php y agregar este contenido:
1 <x-app-layout> 2 <x-slot name="header"> 3 <h2 class="font-semibold text-xl text-gray-800 leading-tight"> 4 {{ __('Tasks') }} 5 </h2> 6 </x-slot> 7 8 <div class="py-12"> 9 <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> 10 <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg"> 11 <div class="p-6 text-gray-900"> 12 <div class="mb-2"> 13 <a href="{{ route('tasks.create') }}" 14 class="p-2 border mb-4"> 15 Create New Task 16 </a> 17 </div> 18 19 <ul class="mt-4"> 20 @foreach ($tasks as $task) 21 <div class="mt-2"> 22 <hr> 23 </div> 24 25 <li> 26 <h1 class="text-2xl"> 27 <strong>{{ $task->title }}</strong> 28 - Due: {{ $task->due_date }} 29 </h1> 30 31 <p class="text-gray-600"> 32 {{ $task->description }} 33 </p> 34 35 <div class="flex gap-2 mt-4"> 36 <div class="p-2 text-white bg-gray-700"> 37 <a href="{{ route('tasks.edit', $task->id) }}"> 38 Edit 39 </a> 40 </div> 41 42 <div class="p-2 text-white bg-red-700 rounded"> 43 <form action="{{ route('tasks.destroy', $task->id) }}" 44 method="POST" 45 style="display:inline;"> 46 @csrf 47 @method('DELETE') 48 <button type="submit">Delete</button> 49 </form> 50 </div> 51 </div> 52 </li> 53 @endforeach 54 </ul> 55 </div> 56 </div> 57 </div> 58 </div> 59 </x-app-layout>
Esta vista incluye un enlace al formulario de creación y recorre todas las tareas para mostrar las que pertenecen al usuario autenticado.
Añadir enlace de navegación para las tareas.
Agrega un enlace a la funcionalidad de tareas desde la navegación de tu aplicación. Vaya a resources/views/layouts/navigation.blade.php y agregue el siguiente código después del enlace de navegación del tablero:
1 // ...existing code ... 2 <div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex"> 3 <x-nav-link :href="route('tasks.index')" :active="request()->routeIs('tasks.index')"> 4 {{ __('Tasks') }} 5 </x-nav-link> 6 </div>
En este punto, puedes probar las operaciones CRUD de tu sistema de gestión de tareas. Asegúrate de que todo funciona correctamente antes de pasar a la siguiente sección.
Crea un comando Artisan personalizado para enviar recordatorios.
Para implementar el sistema de recordatorios de tareas pendientes, crea un comando personalizado de Artisan para enviar recordatorios por correo electrónico y registra el comando para la programación automática.
Para crear un comando personalizado de Artisan, ejecuta el siguiente código en tu terminal:
php artisan make:command SendTaskReminders
Después de crear el comando, actualiza el contenido del archivo app/Console/Commands/SendTaskReminders.php con el siguiente código:
namespace App\Console\Commands; use App\Models\Task; use Carbon\Carbon; use Illuminate\Console\Command; use Illuminate\Support\Facades\Mail; class SendTaskReminders extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'app:send-task-reminders'; /** * The console command description. * * @var string */ protected $description = 'Command description'; /** * Execute the console command. */ public function handle() { $now = Carbon::now(); $upcomingTasks = Task::where('last_notification_date', null)->get(); $upcomingTasks = Task::where('last_notification_date', null) ->where('reminder_time', '>=', $now->clone()->subMinutes(10)) ->get(); foreach ($upcomingTasks as $task) { $emailBody = <<<EOF Hello, This is a reminder for your task: Title: {$task->title} Description: {$task->description} Due Date: {$task->due_date} Please make sure to complete it on time! Regards, Your Task Reminder App EOF; Mail::raw($emailBody, function ($message) use ($task) { $message->to($task->email) ->subject("Task Reminder: {$task->title}"); }); $task->last_notification_date = $now; $task->save(); $this->info("Reminder email sent for task: {$task->title}"); } return self::SUCCESS; } }
La lógica principal del comando Artisan personalizado se escribe en el método handle(). El código obtiene la marca de tiempo actual mediante Carbon::now().
A continuación, consulta la base de datos para obtener todas las tareas donde reminder_time sea menor o igual que la hora actual y donde reminder_time sea mayor o igual que 10 minutos antes de la hora actual. En MongoDB, todas las fechas se almacenan en UTC. Incluso si el servidor usa una zona horaria diferente, no es necesario cambiar la zona horaria.
La query recupera todas las tareas que vencen en los siguientes 10 minutos. El código recorre los resultados y envía recordatorios a los correos electrónicos de los usuarios sobre las tareas que vencerán en los 10 minutos siguientes.
Nota
Para que el programador de tareas funcione correctamente, debes configurar tu aplicación para enviar correos electrónicos. Mailtrap.io es una herramienta útil para probar el envío de correos electrónicos. Para obtener más información, consulta "Enviar correos electrónicos en Laravel".
Programa notificaciones para recordatorios de tareas.
Para finalizar la configuración, programa que el comando Artisan creado en el paso anterior se ejecute cada minuto. Este enfoque ejecuta automáticamente php
artisan app:send-task-reminders cada minuto.
Navegue a routes/console.php y agregue el siguiente código:
// ...existing code ... Schedule::command('app:send-task-reminders')->everyMinute();
Para probar que esto funciona, ejecute el siguiente comando:
php artisan schedule:run
En un servidor de producción, debes configurar una tarea cron para ejecutar el comando php
artisan schedule:run a intervalos regulares.
En un servidor basado en Linux o Unix, puede abrir el archivo de configuración de cron utilizando el siguiente comando:
crontab -e
Agrega el siguiente código a la pestaña de configuración de cron:
* * * * * /usr/bin/php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
Reemplace /usr/bin/php con la ruta a su binario de PHP y /path-to-your-project con la ruta completa a su proyecto de Laravel en su servidor. Guarde y cierre el archivo.
Para verificar que la tarea cron se haya configurado correctamente, ejecute el siguiente comando:
crontab -l
Resumen
Ahora tienes una aplicación de programador de tareas que utiliza Laravel y MongoDB. Este tutorial demostró cómo realizar las siguientes acciones:
Configura un proyecto Laravel para trabajar con MongoDB
Implementar funcionalidades CRUD para el planificador de tareas
Cree un comando personalizado de Laravel Artisan para el sistema de recordatorios
Programa una tarea para ejecutar el comando Artisan a intervalos
Configurar la tarea cron en un servidor basado en Linux
Próximos pasos
Para obtener más información sobre los conceptos abordados en este tutorial, consulta los siguientes recursos:
Ejemplos de uso para ejemplos de código de operaciones comunes
Modelos Eloquent para trabajar con modelos Eloquent