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 este tutorial, asegúrese de tener los siguientes componentes instalados en su entorno de desarrollo:
También debe configurar un clúster de MongoDB Atlas. Para saber cómo configurar un clúster, consulte la guía de introducción.
Pasos
Instalar el paquete MongoDB Laravel.
Para usar MongoDB en su aplicación, debe instalar el paquete Laravel MongoDB y configurarlo en el config/database.php .env.
Instale el paquete utilizando el siguiente comando:
composer require mongodb/laravel-mongodb
Tip
Si se produce un error al ejecutar el comando anterior, asegúrese de que la extensión PHP de MongoDB esté instalada. Para saber cómo instalarla, consulte el paso "Instalar la extensión PHP de MongoDB" en la guía de introducción.
Configurar la conexión a la base de datos.
Una vez finalizada la instalación del paquete MongoDB de Laravel, agregue la conexión de su base de datos MongoDB al archivo config/database.php para completar la configuración. Agregue la siguiente configuración de MongoDB a la matriz connections que contiene las configuraciones para otros tipos de bases de datos:
return [ 'connections' => [ 'mongodb' => [ 'driver' => 'mongodb', 'dsn' => env('MONGODB_URI'), 'database' => 'task_reminder', ], // Other connections here ], ];
Su aplicación obtiene el valor dsn del archivo .env. Navegue hasta el archivo .env. Luego, cree un valor para MONGODB_URI y asígnele el valor de su cadena de conexión de MongoDB.
Tip
Para obtener su cadena de conexión de MongoDB, navegue a su clúster en MongoDB Atlas. Haga clic en el icono Connect y haga clic en el Drivers debajo Connect your application de. Seleccione "PHP" en el Driver menú de selección. Copie la cadena de conexión del cuadro de diálogo. Para obtener información detallada sobre cómo obtener la 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 que funcione con MongoDB, configure la autenticación. Laravel simplifica la implementación de la autenticación ofreciendo paquetes como Laravel Breeze, Laravel Fortify y Laravel Jetstream. Este tutorial utiliza Laravel Breeze para la autenticación.
Instalar Laravel Breeze usando 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 agrega vistas de autenticación, rutas, controladores y otros recursos relacionados a su aplicación.
Configurar 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.
Abra app/Models/User.php y reemplace 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, seleccione el botón Register en su aplicación y cree una nueva cuenta de usuario. Esto almacenará el usuario en su base de datos MongoDB y le permitirá iniciar sesión con esas credenciales. Para este tutorial, puede establecer el nombre de usuario en test@example.com y la contraseña en password.
Para verificar que el paquete Laravel MongoDB se configuró correctamente, cree una ruta para hacer ping a su clúster MongoDB. Agregue 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 es accesible!" en tu navegador.
Cree el modelo de tarea y el controlador.
Cree el modelo y el controlador para la función de programación de tareas utilizando 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 TaskController navegando 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');
Configurar 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\Modeldespués del espacio de nombres es específica de los modelos MongoDB. Anula las funciones de Eloquent implementadas con SQL mediante consultas 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 asignables 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.
Navegue a app/Http/Controllers/TaskController.php y actualice 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 código que maneja las operaciones CRUD del modelo de tarea:
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 de formulario para crear una nueva tarea.El método
store()valida la entrada, asigna el correo electrónico del usuario conectado a la tarea y lo 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 redirecciona a la lista de tareas con un mensaje de éxito para que el usuario pueda dar su opinión.
Crear archivos de vista para el programador de tareas.
En el directorio resources/views, cree una carpeta llamada tasks y cree los siguientes archivos en ella:
create.blade.phpedit.blade.phpindex.blade.php
Navegue a resources/views/tasks/create.blade.php y agregue el siguiente 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 entradas de texto para title y description y entradas de fecha y hora para due date y reminder time.
Navegue a resources/views/tasks/edit.blade.php y agregue el siguiente 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.
Navegue a resources/views/tasks/index.blade.php y agregue el siguiente 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 aquellas que pertenecen al usuario autenticado.
Añadir enlace de navegación para las tareas.
Añade un enlace a la función de tareas desde la navegación de tu aplicación. Ve a resources/views/layouts/navigation.blade.php y añade el siguiente código después del enlace de navegación del panel:
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, puede probar las operaciones CRUD de su sistema de gestión de tareas. Asegúrese de que todo funcione correctamente antes de pasar a la siguiente sección.
Crea un comando Artisan personalizado para enviar recordatorios.
Para implementar el sistema de recordatorio de tareas pendientes, cree un comando Artisan personalizado para enviar recordatorios por correo electrónico y registre el comando para la programación automática.
Para crear un comando Artisan personalizado, ejecute el siguiente código en su terminal:
php artisan make:command SendTaskReminders
Después de crear el comando, actualice 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 es menor o igual a la hora actual y donde reminder_time es mayor o igual a 10 minutos antes de la hora actual. En MongoDB, todas las fechas se almacenan en UTC. Incluso si su servidor usa una zona horaria diferente, no necesita cambiarla.
La consulta recupera todas las tareas que vencen en los próximos 10 minutos. El código recorre los resultados y envía recordatorios a los correos electrónicos de los usuarios sobre las tareas que vencen en los próximos 10 minutos.
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".
Programe notificaciones para recordatorios de tareas.
Para completar la configuración, programe el comando Artisan creado en el paso anterior para que se ejecute cada minuto. Este método 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, debe configurar un trabajo 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
Agregue 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 el trabajo cron esté configurado correctamente, ejecute el siguiente comando:
crontab -l
Resumen
Ahora tienes una aplicación de programación de tareas que usa Laravel y MongoDB. Este tutorial muestra cómo realizar las siguientes acciones:
Configurar un proyecto de Laravel para trabajar con MongoDB
Implementar funciones CRUD para el programador de tareas
Cree un comando Laravel Artisan personalizado para el sistema de recordatorios
Programe una tarea para ejecutar el comando Artisan a intervalos
Configurar el trabajo cron en un servidor basado en Linux
Próximos pasos
Para obtener más información sobre los conceptos tratados en este tutorial, consulte los siguientes recursos:
Ejemplos de uso para ejemplos de código de operaciones comunes
Modelos Eloquent para trabajar con modelos Eloquent