Criando um Lembrete de Tarefa com Laravel e MongoDB
Avalie esse Tutorial
A popularização do Laravel melhorou recentemente à medida que mais desenvolvedores começaram a adotar a tecnologia. O Laravel tem uma sintaxe fácil de entender que aumenta a produtividade ao permitir que o desenvolvedor se concentre nas principais funcionalidades de sua aplicação e não se incomode com tarefas repetitivas, como autenticação e envio de e-mails. Tem uma comunidade muito dinâmica de usuários e ótimos materiais de aprendizado.
Os aplicativos Laravel recém-criados são configurados para usar bancos de dados relacionais. O objetivo deste tutorial é mostrar como usar o MongoDB em um aplicação Laravel. Criaremos um sistema simples de alerta de tarefas para conseguir isso.
As seguintes ferramentas e tecnologias são necessárias para acompanhar eficazmente este tutorial.
- PHP e Composer
- Conhecimento básico do framework Laravel
- Familiaridade com bancos de dados MongoDB e NoSQL
Para trabalhar com o MongoDB, precisamos configurar nosso ambiente de desenvolvimento. Precisamos garantir que todas as dependências de desenvolvimento necessárias sejam instaladas e configuradas corretamente. Certifique-se de ter o seguinte instalado.
Para começar a construir nosso sistema de alerta, a primeira coisa a fazer é criar um novo projeto Laravel. Podemos fazer isso usando o Composer com o comando abaixo:
1 composer create-project laravel/laravel LaravelMongodbProject 2 cd LaravelMongodbProject
Um projeto Laravel recém-criado, quando instalado, vem com configurações padrão para bancos de dados relacionais como MySQL e PostgreSQL. O MongoDB não funciona no Laravel por padrão. Precisamos instalar o pacote Laravel MongoDB e também fazer uma pequena configuração em config/ banco de dados.php. Prossiga para instalar o pacote usando o comando abaixo:
1 composer require mongodb/laravel-mongodb
Quando a instalação do pacote Laravel MongoDB for concluída, a próxima etapa é adicionar nossa conexão de banco de dados MongoDB ao nosso arquivo config/ banco de dados.php para concluir a configuração. Copie o código abaixo e cole-o na
connections
array que contém configurações para outros tipos de banco de dados .1 return [ 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 ],
Vamos dar um momento para explicar. O
dsn
valor é obtido do arquivo .env. Em seu arquivo .env, crie um valor para 'MONGODB_URI
e defina-o como o valor de sua string de conexão do MongoDB Atlas , como abaixo:1 MONGODB_URI="<<MONGODB_ATLAS_CONNECTION_STRING>>" 2 DB_CONNECTION=mongodb
Instalamos e configuramos nosso aplicação para trabalhar com MongoDB. Vamos prosseguir para a autenticação. O Laravel simplifica a implementação da autenticação fornecendo pacotes como Laravel MongoDB, Laravel Fortify e Laravel Jetstream. Neste tutorial, usaremos o Laravel MongoDB para nossa autenticação. Precisamos instalá-lo usando o Composer com o comando abaixo:
1 composer require laravel/breeze --dev
Após a instalação ser concluída, continue executando o próximo conjunto de comandos.
1 php artisan key:generate 2 3 php artisan breeze:install 4 php artisan migrate 5 6 php artisan db:seed 7 npm install 8 npm run dev
Isso solicitará que você escolha sua pilha e pacote de teste preferidos, como na amostra abaixo. Para os fins deste artigo, selecionaremos a primeira opção (Blade e Alpino).
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
Depois, ele adicionará visualizações de autenticação, rotas, comandos e outros recursos relacionados à sua aplicação.
Neste ponto, vamos servir o projeto usando o servidor integrado do Laravel e confirmar que tudo funciona corretamente. Envie seu projeto usando o comando abaixo:
1 php artisan serve
O projeto deve ser atendido em
127.0.0.1:8000
. Caso a porta 8000
já esteja em uso, o Laravel mudará para uma nova porta disponível. Se tudo foi feito corretamente, sua tela deverá ficar como a imagem abaixo
Você pode fazer login usando estas credenciais: o e-mail é "test@ exemplo.com" e a senha é "password".
Para garantir que o pacote Laravel MongoDB foi configurado corretamente, vamos criar uma rota para ping em nosso cluster MongoDB . Adicione o seguinte a route/web.php.
1 Route::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 });
Visite esta rota no seu navegador. Sua tela deverá ficar como a imagem abaixo, se tudo tiver sido feito corretamente:

Vamos criar nosso modelo e controlador para o recurso de agendamento de tarefas. Use o comando abaixo para fazer isso:
1 php artisan make:model Task --resource --controller
O comando acima criará o
Task
modelo no diretório app/Models e o TaskController
no diretório app/HTTP/Controllers com métodos de recursos.Vamos criar uma rota para
TaskController
o. Navegue até rotas/web.php e adicione o seguinte ao arquivo.1 use App\Http\Controllers\TaskController; 2 Route::resource('tasks', TaskController::class)->middleware('auth');
Em seguida, vamos modificar o conteúdo do modelo de tarefa de acordo com as nossas necessidades. Navegue até app/Models/Task.php e substitua o conteúdo pelo seguinte:
1 2 namespace App\Models; 3 use MongoDB\Laravel\Eloquent\Model; 4 class 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 }
O código acima é o nosso modelo de tarefa.
- A
use MongoDB\Laravel\Eloquent\Model
declaração após o namespace é específica para os modelos do MongoDB . Ele substitui os recursos Eloquent implementados com SQL, usando queries MongoDB . - O
protected $table = 'tasks'
é opcional. É o nome da coleção MongoDB que é usado para extrair os documentos deste modelo. - O
protected $fillable = ['title', 'description', 'due_date', 'email', 'reminder_time']
especifica as propriedades atribuíveis em massa.
Uma das funcionalidades exclusivas do MongoDB é que ele não precisa de migrações como os bancos de dados relacionais. Isso significa que você pode adicionar novos campos diretamente aos seus documentos sem precisar atualizar o modelo ou criar migrações. Isso é particularmente útil ao lidar com dados dinâmicos.
Em seguida, vamos modificar nosso controlador. Navegue até app/HTTP/Controllers/TaskController.php e atualize o conteúdo com o código abaixo:
1 2 namespace App\Http\Controllers; 3 use App\Models\Task; 4 use Carbon\Carbon; 5 use Illuminate\Http\Request; 6 class 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 }
Nosso recém-criado
TaskController
acima contém código que lida com as operações CRUD do nosso modelo de tarefa. O método index recupera todas as tarefas pertencentes ao usuário conectado e as envia para o arquivo index.brade.php para serem exibidas no frontend.O método create retorna a visualização do formulário para criar uma nova tarefa, enquanto o método store valida a entrada, atribui o e-mail do usuário conectado à tarefa e a salva no banco de dados.
Para atualizações, o método de edição recupera a tarefa específica a ser editada e a exibe em um formulário de edição. Quando esse formulário é enviado, ele chama o método de atualização que salva a tarefa editada em nossa coleção de tarefas do MongoDB .
O método Destruir exclui uma tarefa específica. Cada operação redireciona de volta para a lista de tarefas com uma mensagem de sucesso para feedback do usuário.
Vamos criar arquivos de visualização para nosso agendador de tarefas. No diretório recursos/visualizações, crie uma pasta denominada /tasks e crie os seguintes arquivos nela:
- create.lade.php
- edit.lade.php
- index.lade.php
Navegue até resources/views/create.brade.php e substitua o conteúdo da página pelo seguinte:
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
No código acima, adicionamos
HTML
para o formulário de criação. O formulário contém entrada de texto para title
e description
e entrada de data e hora para due date
e reminder time
. Se o seu código estiver correto, sua tela deverá ficar como a imagem abaixo.
Faça o mesmo para edit.brade.php. Navegue até resources/views/edit.brade.php e adicione o código abaixo ao conteúdo da página:
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>
O
edit
contém os mesmos campos de entrada que o create
formulário acima. Ela é carregada com os dados da tarefa que está sendo editada.Por último, acesse resources/views/index.lade.php e substitua o conteúdo pelo código abaixo:
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>
No código acima, temos um link para o
create
formulário. Ele também percorre todos os alertas e exibe aqueles pertencentes a esse usuário.
Adicionar rota
Em seguida, precisamos adicionar um link para a funcionalidade de tarefa a partir da navegação do nosso aplicação . Abra resouces/views/layouts/navigation.brade.php e adicione a seguinte linha de código logo após o link de navegação do painel.
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>
Neste ponto, podemos testar a operação CRUD de nosso sistema de gerenciamento de tarefas. Certifique-se de que tudo funcione corretamente antes de passar para a próxima seção.
Vamos implementar o sistema de alerta para as tarefas vencidas. Para fazer isso, vamos:
- Crie um comando manual personalizado para enviar avisos por e-mail.
- Registre o comando para agendamento automático. Vamos criar um comando de mestre personalizado usando o comando abaixo:
1 php artisan make:command SendTaskReminders
Após completar o comando, atualize o conteúdo de app/Console/Commands/SendTaskRemiders.php com o código abaixo:
1 2 3 namespace App\Console\Commands; 4 5 use App\Models\Task; 6 use Carbon\Carbon; 7 use Illuminate\Console\Command; 8 use Illuminate\Support\Facades\Mail; 9 10 class 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 }
A lógica principal do nosso comando customizado está escrita no
handle()
método. A partir do código acima, obtemos o registro de data/hora atual usando Carbon::now()
.Em seguida, consultamos o banco de dados para obter todas as tarefas em que
reminder_time
é menor ou igual ao tempo atual (o valor de $ now) e onde reminder_time
é maior ou igual a 10 minutos antes do tempo, com esta linha de código: 'reminder_time','>=',$now->clone()->subMinutes(10)
. No MongoDB, todas as datas são armazenadas em UTC. Mesmo que o seu servidor utilize um fuso horário diferente, você não precisa alterá-lo.Para lançar mais luz, vamos presumir que o tempo atual é $ now = 2024-10-22 15:00:00. A query de alerta de tarefas obtém todas as tarefas entre 2024-10-22 14:50:00 e 2024-10-22 15:00:00. Buscamos todas as tarefas vencidas em 10 minutos.
Em seguida, percorremos o resultado e enviamos alertas para os e-mails dos usuários sobre as tarefas que serão executadas nos próximos 10 minutos.
Para que o agendador de tarefas funcione corretamente, você deve configurar seu aplicação para enviar e-mails. Mailtrap.io é uma ótima ferramenta para testar o envio de e-mails. Obtenha uma explicação detalhada de como configurar seu aplicação para enviar e-mails usando o Mailtrap.
Para envolver tudo, precisamos agendar o comando de criação criado acima para executar a cada minuto. Pense nisso como uma maneira de executar automaticamente
php artisan app:send-task-reminders
a cada minuto.Existem diferentes abordagens para agendar uma tarefa no Laravel. Neste tutorial, estamos trabalhando com a versão 11.9 do Laravel, que é a versão mais recente no momento em que este artigo foi escrito. Para prosseguir, navegue até roles/console.php e adicione o seguinte:
1 //...existing code ... 2 Schedule::command('app:send-task-reminders')->everyMinute();
Para testar se isso funciona, execute o comando abaixo:
1 php artisan schedule:run
Em um servidor de produção, você precisará configurar um tarefa cron para executar o
php artisan schedule:run
comando em intervalos regulares.Em um servidor baseado em Linux ou Unix, você pode abrir seu arquivo de configuração do cron usando o comando abaixo:
1 crontab -e
Adicione o código abaixo na aba de configuração do cron:
1 * * * * * /usr/bin/php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
Para que isso funcione corretamente, substitua
/usr/bin/php
pelo caminho para seu binário PHP e /path-to-your-project
pelo caminho completo para seu projeto Laravel no seu servidor, então salve e saia.Você pode verificar se tudo funciona bem digitando este comando abaixo:
1 crontab -l
Verificamos o fim deste tutorial; ótimo tarefa se você me seguiu. Agora, para recapitular, neste tutorial, percorremos o processo de criação de um agendador de tarefas no Laravel e no MongoDB. Algumas das principais implementações foram:
- Configurar um projeto Laravel para trabalhar com MongoDB.
- Implementação de recursos CRUD para nosso agendador de tarefas.
- Criando um comando manual personalizado do Laravel para o nosso sistema de alerta.
- Agendando uma tarefa para executar o comando do mestre em intervalos.
- Percorrendo as etapas para configurar o cron tarefa em um servidor baseado em Linux.
Encontre o projeto no Github. Sinta-se livre para cloná-lo, inscreva-se noMongoDB Atlas e personalize-o de acordo com suas necessidades específicas. Para obter mais suporte, faça parte da Comunidade de desenvolvedores do MongoDB .
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.