Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Saiba por que o MongoDB foi selecionado como um líder no 2024 Gartner_Magic Quadrupnt()
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

Building a Task Reminder With Laravel and MongoDB

Anumadu Moses11 min read • Published Jan 08, 2025 • Updated Jan 08, 2025
AtlasPHP
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
The popularity of Laravel has improved recently as more developers have started to adopt the technology. Laravel has an easy-to-understand syntax that boosts productivity by letting the developer focus on the core features of their application and not bother with repetitive tasks like authentication and sending emails. It has a very vibrant community of users and great learning materials.
Freshly created Laravel applications are configured to use relational databases. The purpose of this tutorial is to show how to use MongoDB in a Laravel application. We will build a simple task reminder system to achieve this.

Pré-requisitos

The following tools and technologies are required to follow along effectively with this tutorial.
  • A free MongoDB Atlas cluster
  • PHP and Composer
  • Basic knowledge of the Laravel framework
  • Familiarity with MongoDB and NoSQL databases

Configuração do ambiente

To work with MongoDB, we need to configure our development environment. We need to ensure that all the necessary development dependencies are installed and configured properly. Make sure you have the following installed.

Configuração do projeto

To get started building our reminder system, the first thing to do is create a new Laravel project. We can do so using the composer with the command below:
1composer create-project laravel/laravel LaravelMongodbProject
2cd LaravelMongodbProject

Install MongoDB Laravel package

A freshly created Laravel project when installed comes with default configurations for relational databases like MySql and PostgreSQL. MongoDB does not work in Laravel by default. We need to install the Laravel MongoDB package and also do a little configuration in config/database.php. Proceed to install the package using the command below:
1composer require mongodb/laravel-mongodb

Configure database

Once the installation of the Laravel MongoDB package is completed, the next step is to add our MongoDB database connection to our config/database.php file to complete the configuration. Copy the code below and paste it in the connections array that contains configurations for other database types.
1return [
2 'connections' => [
3 'mongodb' => [
4 'driver' => 'mongodb',
5 'dsn' => env('MONGODB_URI'),
6 'database' => 'YOUR_DATABASE_NAME',
7 ],
8 //You can keep other existing connections
9 ],
Let's take a moment to explain. The dsn value is obtained from the .env file. In your .env file, create a value for 'MONGODB_URI and set it to the value of your MongoDB Atlas connection string, like below:
1MONGODB_URI="<<MONGODB_ATLAS_CONNECTION_STRING>>"
2DB_CONNECTION=mongodb

Authentication with Laravel Breeze

We have installed and configured our application to work with MongoDB. Let's proceed to authentication. Laravel simplifies the implementation of authentication by providing packages like Laravel Breeze, Laravel Fortify, and Laravel Jetstream. In this tutorial, we will use Laravel Breeze for our authentication. We need to install it using Composer with the command below:
1composer require laravel/breeze --dev
Once the installation is complete, proceed by running the next set of commands.
1php artisan key:generate
2
3php artisan breeze:install
4php artisan migrate
5
6php artisan db:seed
7npm install
8npm run dev
This will prompt you to choose your preferred stack and testing package like the sample below. For the purpose of this article, we will select the first option (Blade and Alpine).
1┌ Which Breeze stack would you like to install? ───────────────┐
2│ > ● Blade with Alpine │
3│ ○ Livewire (Volt Class API) with Alpine │
4│ ○ Livewire (Volt Functional API) with Alpine │
5│ ○ React with Inertia │
6│ ○ Vue with Inertia │
7│ ○ API only
Afterward, it will add authentication views, routes, controllers, and other related resources to your application.
At this point, let's serve the project using Laravel's built-in server and confirm that everything works properly. Serve your project using the command below:
1php artisan serve
The project should be served at 127.0.0.1:8000. In case the port 8000 is already in use, Laravel will switch to a new available port. If everything was done right, your screen should look like the image below
Image of Laravel default landing
You can log in using these credentials: email is "test@example.com" and password is "password".
To make sure that the Laravel MongoDB package was configured properly, let's create a route to ping our MongoDB cluster. Add the following to route/web.php.
1Route::get('/ping', function (Request $request) {
2 $connection = DB::connection('mongodb');
3 try {
4 $connection->command(['ping' => 1]);
5 $msg = 'MongoDB is accessible!';
6 } catch (Exception $e) {
7 $msg = 'You are not connected to MongoDB. Error: ' . $e->getMessage();
8 }
9 return ['msg' => $msg];
10});
Visit this route in your browser. Your screen should look like the image below, if everything was done right:
insira a descrição da imagem aqui

Creating the task reminder system

Let's create our model and controller for the task scheduling feature. Use the command below to do so:
1php artisan make:model Task --resource --controller
The command above will create the Task model in the app/Models directory and the TaskController in the app/Http/Controllers directory with resource methods.
Let's create a route for the TaskController. Navigate to routes/web.php and add the following to the file.
1use App\Http\Controllers\TaskController;
2Route::resource('tasks', TaskController::class)->middleware('auth');
Next, let's modify the content of the task model to our needs. Navigate to app/Models/Task.php and replace the content with the following:
1<?php
2namespace App\Models;
3use MongoDB\Laravel\Eloquent\Model;
4class Task extends Model
5{
6 protected $connection = 'mongodb';
7 protected $table = 'tasks';
8 protected $fillable = [
9 'title', 'description', 'due_date', 'email', 'reminder_time', 'last_notification_date'
10 ];
11}
The code above is our task model.
  • The use MongoDB\Laravel\Eloquent\Model statement after the namespace is specific to MongoDB models. It overrides the Eloquent features implemented with SQL, using MongoDB queries.
  • The protected $table = 'tasks' is optional. It is the name of the MongoDB collection that is used to tore the documents from this model.
  • The protected $fillable = ['title', 'description', 'due_date', 'email', 'reminder_time'] specifies the mass assignable properties.
One of the unique features of MongoDB is that it doesn't need migrations like relational databases do. This means you can add new fields directly to your documents without having to update the model or create migrations. This is particularly helpful in handling dynamic data.
Next, let's modify our controller. Navigate to app/Http/Controllers/TaskController.php and update the content with the code below:
1<?php
2namespace App\Http\Controllers;
3use App\Models\Task;
4use Carbon\Carbon;
5use Illuminate\Http\Request;
6class TaskController extends Controller
7{
8 /**
9 * Display a listing of the resource.
10 */
11 public function index()
12 {
13 $tasks = Task::where('email', auth()->user()->email)->get();
14 return view('tasks.index', compact('tasks'));
15 }
16
17 /**
18 * Show the form for creating a new resource.
19 */
20 public function create()
21 {
22 return view('tasks.create');
23 }
24
25 /**
26 * Store a newly created resource in storage.
27 */
28 public function store(Request $request)
29 {
30 $request->validate([
31 'title' => 'required|string|max:255',
32 'description' => 'nullable|string',
33 'due_date' => 'required|date',
34 'reminder_time' => 'required|date',
35 ]);
36
37 $data = $request->all();
38 $data['due_date'] = Carbon::parse($request->due_date);
39 $data['reminder_time'] = Carbon::parse($request->reminder_time);
40 $data['email'] = auth()->user()->email;
41
42 $data['last_notification_date'] = null;
43
44 Task::create($data);
45
46 return redirect()->route('tasks.index')->with('success', 'Task created successfully.');
47 }
48
49 /**
50 * Display the specified resource.
51 */
52 public function show(string $id)
53 {
54 //
55 }
56
57 /**
58 * Show the form for editing the specified resource.
59 */
60 public function edit(string $id)
61 {
62 $tasks = Task::where('id', $id)->get();
63 return view('tasks.edit', ['tasks' => $tasks]);
64 }
65
66 /**
67 * Update the specified resource in storage.
68 */
69 public function update(Request $request, string $id)
70 {
71 $task = Task::findOrFail($id);
72 $data = $request->all();
73
74 $data['due_date'] = Carbon::parse($request->due_date)->format('Y-m-d H:i:s');
75 $data['reminder_time'] = Carbon::parse($request->reminder_time)->format('Y-m-d H:i:s');
76 $task->update($data);
77
78 return redirect()->route('tasks.index')->with('success', 'Task updated successfully.');
79 }
80
81 /**
82 * Remove the specified resource from storage.
83 */
84 public function destroy(string $id)
85 {
86 $task = Task::findOrFail($id);
87 $task->delete();
88 Return redirect()->route('tasks.index')->with('success', 'Task deleted successfully.');
89 }
90}
Our newly created TaskController above contains code that handles the CRUD operations of our task model. The index method retrieves all tasks belonging to the logged-in user and sends them to the index.blade.php file to be displayed on the front end.
The create method returns the form view for creating a new task, while the store method validates the input, assigns the logged-in user's email to the task, and saves it to the database.
For updates, the edit method retrieves the specific task to be edited and displays it in an edit form. When this form is submitted, it calls the update method which saves the edited task in our MongoDB task collection.
The destroy method deletes a specific task. Each operation redirects back to the task's list with a success message for user feedback.
Let's create view files for our task scheduler. In the resources/views directory, create a folder named /tasks and create the following files in it:
  • create.blade.php
  • edit.blade.php
  • index.blade.php
Navigate to resources/views/create.blade.php and replace the content of the page with the following:
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 <form action="{{ route('tasks.store') }}" method="POST">
14 @csrf
15 <div class="mb-4">
16 <label for="title" class="block text-gray-700">Title:</label>
17 <input type="text" name="title" id="title" required class="border border-gray-300 p-2 w-full" value="{{ old('title') }}">
18 @error('title')
19 <p class="text-red-500">{{ $message }}</p>
20 @enderror
21 </div>
22 <div class="mb-4">
23 <label for="description" class="block text-gray-700">Description:</label>
24 <textarea name="description" id="description" class="border border-gray-300 p-2 w-full">{{ old('description') }}</textarea>
25 </div>
26 <div class="mb-4">
27 <label for="due_date" class="block text-gray-700">Due Date:</label>
28 <input type="date" name="due_date" id="due_date" required class="border border-gray-300 p-2 w-full" value="{{ old('due_date') }}">
29 @error('due_date')
30 <p class="text-red-500">{{ $message }}</p>
31 @enderror
32 </div>
33 <div class="mb-4">
34 <label for="reminder_time" class="block text-gray-700">Reminder Time:</label>
35 <input type="datetime-local" name="reminder_time" id="reminder_time" class="border border-gray-300 p-2 w-full" value="{{ old('reminder_time') }}">
36 </div>
37 <button type="submit" class="bg-green-600 text-white text-gray-399 p-2 border rounded">Create Task</button>
38 </form>
39 </div>
40 </div>
41 </div>
42 </div>
43</x-app-layout>
44
In the code above, we added HTML for the create form. The form contains text input for title and description and date and time input for due date and reminder time. If your code is right, your screen should look like the image below.
Image of the dashboard with a form for creating a new task.
Do the same for edit.blade.php. Navigate to resources/views/edit.blade.php and add the code below to the content of the page:
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 <div class="mb-4">
17 <label for="title" class="block text-gray-700">Title:</label>
18 <input type="text" name="title" id="title" required class="border border-gray-300 p-2 w-full" value="{{ old('title', $task->title) }}">
19 @error('title')
20 <p class="text-red-500">{{ $message }}</p>
21 @enderror
22 </div>
23 <div class="mb-4">
24 <label for="description" class="block text-gray-700">Description:</label>
25 <textarea name="description" id="description" class="border border-gray-300 p-2 w-full">{{ old('description', $task->description) }}</textarea>
26 </div>
27 <div class="mb-4">
28 <label for="due_date" class="block text-gray-700">Due Date:</label>
29 <input type="date" name="due_date" id="due_date" required class="border border-gray-300 p-2 w-full" value="{{ old('due_date', $task->due_date) }}">
30 @error('due_date')
31 <p class="text-red-500">{{ $message }}</p>
32 @enderror
33 </div>
34 <div class="mb-4">
35 <label for="reminder_time" class="block text-gray-700">Reminder Time:</label>
36 <input type="datetime-local" name="reminder_time" id="reminder_time" class="border border-gray-300 p-2 w-full" value="{{ old('reminder_time', $task->reminder_time) }}">
37 </div>
38 <button type="submit" class="bg-blue-500 text-white p-2 rounded">Update Task</button>
39 </form>
40 @endforeach
41 </div>
42 </div>
43 </div>
44 </div>
45</x-app-layout>
The edit contains the same input fields as the create form above. It is loaded with the data of the task currently being edited.
Lastly, navigate to resources/views/index.blade.php and replace the content with the code below:
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') }}" class="p-2 border mb-4">Create New Task</a>
14 </div>
15 <ul class="mt-4">
16 @foreach ($tasks as $task)
17 <div class="mt-2">
18 <hr>
19 </div>
20 <li>
21 <h1 class="text-2xl">
22 <strong>{{ $task->title }}</strong> - Due: {{ $task->due_date }}
23 </h1>
24 <p class="text-gray-600">
25 {{ $task->description }}
26 </p>
27 <div class="flex gap-2 mt-4">
28 <div class="p-2 text-white bg-gray-700">
29 <a href="{{ route('tasks.edit', $task->id) }}">Edit</a>
30 </div>
31 <div class="p-2 text-white bg-red-700 rounded">
32 <form action="{{ route('tasks.destroy', $task->id) }}" method="POST" style="display:inline;">
33 @csrf
34 @method('DELETE')
35 <button type="submit">Delete</button>
36 </form>
37 </div>
38 </div>
39 </li>
40 @endforeach
41 </ul>
42 </div>
43 </div>
44 </div>
45 </div>
46</x-app-layout>
In the code above, we have a link to the create form. It also loops through all the reminders and displays those belonging to this user.
insira a descrição da imagem aqui
Add route
Next, we need to add a link to the task feature from our application navigation. Open resouces/views/layouts/navigation.blade.php and add the following line of code just after the dashboard navigation link.
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>
At this point, we should be able to test the CRUD operation of our task management system. Ensure that everything works correctly before moving on to the next section.

Setting reminders using Laravel task scheduling

Let's proceed to implementing the reminder system for due tasks. To do this we will:
  • Create a custom artisan command to send reminders through email.
  • Register the command for automatic scheduling. Let's create a custom artisan command using the command below:
1php artisan make:command SendTaskReminders
Once the command is completed, update the content of app/Console/Commands/SendTaskReminders.php with the code below:
1<?php
2
3namespace App\Console\Commands;
4
5use App\Models\Task;
6use Carbon\Carbon;
7use Illuminate\Console\Command;
8use Illuminate\Support\Facades\Mail;
9
10class SendTaskReminders extends Command
11{
12 /**
13 * The name and signature of the console command.
14 *
15 * @var string
16 */
17 protected $signature = 'app:send-task-reminders';
18
19 /**
20 * The console command description.
21 *
22 * @var string
23 */
24 protected $description = 'Command description';
25
26 /**
27 * Execute the console command.
28 */
29 public function handle()
30 {
31 $now = Carbon::now();
32 $upcomingTasks = Task::where('last_notification_date', null)->get();
33
34 $upcomingTasks = Task::where('last_notification_date', null)
35
36 ->where('reminder_time', '>=', $now->clone()->subMinutes(10))
37
38 ->get();
39
40 foreach ($upcomingTasks as $task) {
41 $emailBody = <<<EOF
42 Hello,
43 This is a reminder for your task:
44 Title: {$task->title}
45 Description: {$task->description}
46 Due Date: {$task->due_date}
47 Please make sure to complete it on time!
48 Regards,
49 Your Task Reminder App
50 EOF;
51
52 Mail::raw($emailBody, function ($message) use ($task) {
53 $message->to($task->email)
54 ->subject("Task Reminder: {$task->title}");
55 });
56
57 $task->last_notification_date = $now;
58 $task->save();
59 $this->info("Reminder email sent for task: {$task->title}");
60 }
61
62 return self::SUCCESS;
63 }
64}
The main logic of our custom artisan command is written in the handle() method. From the code above, we get the current timestamp using Carbon::now().
Next, we query the database to get all the tasks where reminder_time is less than or equal to the current time (the value of $now) and where reminder_time is greater than or equal to 10 minutes before the time, with this line of code: 'reminder_time','>=',$now->clone()->subMinutes(10). In MongoDB, all dates are stored in UTC. Even if your server uses a different timezone, you don't need to change it.
To throw more light, let's assume that the current time is $now = 2024-10-22 15:00:00. The task reminder query fetches all tasks between 2024-10-22 14:50:00 and 2024-10-22 15:00:00. We fetch all tasks that are due in 10 minutes.
Then, we loop through the result and send reminders to the user emails of tasks that will be due in the next 10 minutes.
For the task scheduler to work properly, you must configure your application to send emails. Mailtrap.io is a great tool for testing email sending. Get a detailed explanation of how to configure your application to send emails using Mailtrap.

Scheduling notifications for task reminders

To wrap it all up, we need to schedule the artisan command created above to run every minute. Think of this as a way to automatically run php artisan app:send-task-reminders every minute.
There are different approaches to scheduling a task in Laravel. In this tutorial, we are working with Laravel version 11.9, which is the most recent version at the time of this writing. To proceed, navigate to routes/console.php and add the following:
1//...existing code ...
2Schedule::command('app:send-task-reminders')->everyMinute();
To test that this works, run the command below:
1php artisan schedule:run
On a production server, you will need to configure a cron job to run the php artisan schedule:run command at regular intervals.
In a Linux- or Unix-based server, you can open your cron configuration file using the command below:
1crontab -e
Add the code below into the cron configuration tab:
1* * * * * /usr/bin/php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
For this to work properly, replace /usr/bin/php with the path to your PHP binary and /path-to-your-project with the full path to your Laravel project on your server, then save and exit.
You can verify that everything works fine by typing this command below:
1crontab -l

Conclusão

We have come to the end of this tutorial; great job if you followed along. Now, for a recap, in this tutorial, we walked through the process of creating a task scheduler in Laravel and MongoDB. Some of the key implementations were:
  • Configuring a Laravel project to work with MongoDB.
  • Implementing CRUD features for our tasks scheduler.
  • Creating a custom Laravel artisan command for our reminder system.
  • Scheduling a task to run the artisan command in intervals.
  • Walking through the steps to configure the cron job on a Linux-based server.
Find the project on GitHub. Feel free to clone it, sign up for MongoDB Atlas, and customize it to your specific needs. For more support, join the MongoDB Developer Community.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Como criar um sistema RAG usando o Claude 3 Opus e o MongoDB


Aug 28, 2024 | 15 min read
Tutorial

RAG interativo com MongoDB Atlas + API de chamada de função


Sep 18, 2024 | 16 min read
Tutorial

Usando o driver Node.js MongoDB com AWS Lambda


Jan 23, 2024 | 5 min read
Artigo

Capturando e armazenando óptica do mundo real com o MongoDB Atlas, o GPT-4 da OpenAI e o PyMongo


Sep 04, 2024 | 7 min read
Sumário