Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

チュートリアル: Laravel と MongoDB でタスクリマインダーをビルドする

このチュートリアルでは、簡単なタスクトリガー システムを構築して、LambdaアプリケーションでMongoDBを使用する方法を学習できます。アプリケーションでは、タスクを作成、読み取り、更新、および削除することができます。さらに、スケジュールされた時間に基づいて今後のタスクのリダイレクトをメールで送信します。

このチュートリアルを開始する前に、開発環境に次のコンポーネントがインストールされていることを確認してください。

  • PHPMongoDB PHP拡張機能

  • Lambel

  • Composer

  • NPM

また、 MongoDB Atlasクラスターを設定する必要があります。クラスターのセットアップ方法を学ぶには、クイック スタートガイドを参照してください。

1

Composer を使用して新しい Lambdaプロジェクトを作成し、プロジェクトディレクトリに移動します。

composer create-project laravel/laravel LaravelMongodbProject
cd LaravelMongodbProject
2

アプリケーションでMongoDBを使用するには、Lambda MongoDBパッケージをインストールし、それを config/database.phpファイルで構成する必要があります。

次のコマンドを使用してパッケージをインストールします。

composer require mongodb/laravel-mongodb

Tip

上記のコマンドを実行するとエラーが発生した場合は、 MongoDB PHP拡張機能がインストールされていることを確認してください。インストールする方法については、使用開始ガイドのMongoDB PHP拡張機能のインストールの手順を参照してください。

3

Lambda MongoDBパッケージのインストールが完了したら、config/database.phpファイルにMongoDBデータベース接続を追加して構成を完了します。次のMongoDB構成を、他のデータベースタイプの構成を含む connections 配列に追加します。

return [
'connections' => [
'mongodb' => [
'driver' => 'mongodb',
'dsn' => env('MONGODB_URI'),
'database' => 'task_reminder',
],
// Other connections here
],
];

アプリケーションは.envファイルから dsn 値を取得します。.envファイルに移動します。次に、MONGODB_URI の値を作成し、それをMongoDB接続文字列の値に設定します。

Tip

MongoDB接続文字列を取得するには、 MongoDB Atlasのクラスターに移動します。Connect ボタンをクリックし、Connect your application の下の Drivers をクリックします。Driver 選択メニューから [PHP] を選択します。ダイアログ ボックスから接続文字列をコピーします。接続文字列を取得する方法の詳細については、接続文字列の作成 を参照してください。

.envファイルで、DB_CONNECTION の値を mongodb に設定して、アプリケーションのデフォルト接続とします。次のコードに示すように、SESSION_DRIVER の値を編集し、mongodb に設定します。

MONGODB_URI=mongodb+srv://YOUR_MONGODB_CONNECTION_STRING
DB_CONNECTION=mongodb
// Other DB_ values here ...
SESSION_DRIVER=mongodb
4

アプリケーションをインストールしてMongoDBで動作するように構成したら、認証を設定します。Lambda は、Lalavel Releases、Lalavel Fortify、Lambel jetstream などのパッケージを提供することで認証実装を簡素化します。このチュートリアルでは、認証に Laravel Breeze を使用します。

Composer を使用して Lambda をインストールします。

composer require laravel/breeze --dev

インストールが完了したら、次のコマンドを実行します。

php artisan key:generate
php artisan breeze:install
php artisan migrate
php artisan db:seed
npm install
npm run dev

希望するスタックとテストパッケージを選択するよう求められます。このチュートリアルでは、最初のオプションである [Blain with Alplica ] を選択します。

┌ 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 │
└──────────────────────────────────────────────────────────────┘

このコマンドは、認証ビュー、ルート、コントローラー、およびその他の関連リソースをアプリケーションに追加します。

5

Lambda はSQLデータベース用のデフォルトのユーザーモデルを作成します。MongoDBで動作し、レート制限の互換性の問題を解決するには、これを更新する必要があります。

app/Models/User.php を開き、その内容を次のように置き換えます。

<?php
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',
];
}
}
6

Lambda の組み込みサーバーを使用してプロジェクトを処理し、すべてが正常に動作することを確認します。Lambdaプロジェクトディレクトリで、次のコマンドを実行します。

php artisan serve

このプロジェクトは127.0.0.1:8000 で提供されています。ポート 8000 がすでに使用されている場合、Lambel は新しく使用可能なポートに切り替え、ターミナルに出力します。

認証システムをテストするには、アプリケーションで [Register] ボタンを選択し、新しいユーザー アカウントを作成します。これにより、ユーザーがMongoDBデータベースに保存され、それらの認証情報でログできるようになります。このチュートリアルでは、ユーザー名をtest@example.com に、パスワードを password に設定できます。

Lambda MongoDBパッケージが正しく構成されていることを確認するには、 MongoDBクラスターにpingためのルートを作成します。以下を 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];
});

ブラウザでこのルートにアクセスしてください。正しい構成では、「MongoDBがアクセス可能です。」というメッセージが表示されます。ブラウザに表示されます。

7

次のコマンドを使用して、タスク予定機能のモデルとコントローラーを作成します。

php artisan make:model Task --resource --controller

このコマンドは、リソースメソッドを使用して、app/Modelsディレクトリに Task モデルを作成し、app/Http/Controllersディレクトリに TaskController モデルを作成します。

routes/web.php に移動し、次のコードを追加して、TaskController のルートを作成します。

use App\Http\Controllers\TaskController;
// Other route definitions...
Route::resource('tasks', TaskController::class)->middleware('auth');
8

app/Models/Task.php に移動し、ファイルの内容を次のコードで置き換えます。

<?php
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'
];
}

このコードは、次の仕様でタスクモデルを作成します。

  • 名前空間の後の use MongoDB\Laravel\Eloquent\Model ステートメントはMongoDBモデルに固有です。MongoDBクエリを使用することで、 SQLで実装された Elastic 機能を上書きします。

  • protected $table = 'tasks'プロパティは任意です。このモデルからのドキュメントを保存するために使用されるMongoDBコレクションの名前を指定します。

  • protected $fillableプロパティは、一括割り当て可能なプロパティを指定します。

Tip

MongoDBのユニークな機能の 1 つは、関係データベースのような移行が必要ないことです。モデルを更新したり移行を作成したりすることなく、ドキュメントに新しいフィールドを直接追加できます。この機能は、動的データを処理するのに便利です。

9

app/Http/Controllers/TaskController.php に移動し、次のコードでコンテンツを更新します。

<?php
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.');
}
}

TaskControllerクラスには、タスクモデルのCRUD操作を取り扱うコードが含まれています。

  • index() メソッドは、ログイン ユーザーに属するすべてのタスクを取得し、それを index.blade.phpファイルに送信して表示します。

  • create() メソッドは、 新しいタスクを作成するためのフォームビューを返します。

  • store() メソッドは入力を検証し、ログイン ユーザーのメールをタスクに割り当て、それをデータベースに保存します。

  • edit() メソッドは、編集する特定のタスクを取得し、編集フォームに表示します。

  • update() メソッドは編集したタスクをMongoDBタスクコレクションに保存します。

  • destroy() メソッドは特定のタスクを削除します。

各操作は、 ユーザーフィードバックの成功メッセージとともにタスクリストにリダイレクトされます。

10

resources/viewsディレクトリに、tasks という名前のフォルダーを作成し、その中に次のファイルを作成します。

  • create.blade.php

  • edit.blade.php

  • index.blade.php

resources/views/tasks/create.blade.php に移動し、次のコンテンツを追加します。

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>

フォームには、titledescription のテキスト入力と、due datereminder time の日付と時刻の入力が含まれています。

resources/views/tasks/edit.blade.php に移動し、次のコンテンツを追加します。

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>

編集フォームには、作成フォームと同じ入力フィールドが含まれ、現在編集中のタスクのデータが読み込まれます。

resources/views/tasks/index.blade.php に移動し、次のコンテンツを追加します。

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>

このビューには、作成フォームへのリンクが含まれており、すべてのタスクをループ処理して、認証されたユーザーに属するタスクを表示します。

11

アプリケーションナビゲーションからタスク機能へのリンクを追加します。resources/views/layouts/navigation.blade.php にGo、ダッシュボード ナビゲーション リンクの後に次のコードを追加します。

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>

この点で、タスクマネジメントシステムのCRUD操作をテストできます。次のセクションに入る前に、すべてが正しく動作していることを確認してください。

12

期限が切れたタスクのトリガー システムを実装するには、メールでトリガーを送信するためのカスタム アーティアン コマンドを作成し、コマンドを自動スケジュール用に登録します。

カスタム アーティザ コマンドを作成するには、ターミナルで次のコードを実行します。

php artisan make:command SendTaskReminders

コマンドを作成した後、次のコードで app/Console/Commands/SendTaskReminders.phpファイルの内容を更新します。

<?php
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;
}
}

カスタム アーティファクト コマンドのメイン ロジックは handle() メソッドに記述されています。このコードは Carbon::now() を使用して現在のタイムスタンプを取得します。

次に、データベースをクエリして、reminder_time が現在の時刻以下、かつ reminder_time が現在の時刻の 10 分以上であるすべてのタスクを取得します。MongoDBでは、すべての日付は UTC で保存されます。サーバーが別の タイムゾーンを使用している場合でも、 タイムゾーンを変更する必要はありません。

クエリは、次の 10 分に期限されるすべてのタスクを取得します。このコードは結果をループ処理し、次の 10 分に期限が切れるタスクのユーザーのメールにリマインダーを送信します。

注意

タスクタスクが正しく動作するには、アプリケーションがメールを送信するように構成する必要があります。Emailtap.io は、メールの送信をテストするのに便利なツールです。Laravelでメールを送信するについて学ぶには、こちらをご覧ください。

13

設定を完了するには、前のステップで作成された Artisan コマンドを 1 分ごとに実行するように予定します。このアプローチでは、1 分ごとに php artisan app:send-task-reminders が自動的に実行されます。

routes/console.php に移動し、次のコードを追加します。

// ...existing code ...
Schedule::command('app:send-task-reminders')->everyMinute();

これが動作するかどうかをテストするには、次のコマンドを実行します。

php artisan schedule:run

本番環境サーバーでは、php artisan schedule:run コマンドを定期的に実行するように cronジョブを構成する必要があります。

Linuxまたは Unix ベースのサーバーでは、次のコマンドを使用して cron構成ファイルを開くことができます。

crontab -e

次のコードを cron 構成タブに追加します。

* * * * * /usr/bin/php /path-to-your-project/artisan schedule:run >>
/dev/null 2>&1

/usr/bin/php をPHPバイナリへのパスに置き換え、/path-to-your-project をサーバー上の Lambdaプロジェクトへの完全なパスに置き換えます。ファイルを保存して終了します。

cronジョブが正しく設定されていることを確認するには、次のコマンドを実行します。

crontab -l

これで、 Lambda とMongoDBを使用するタスクスケジューラーアプリケーションができました。このチュートリアルでは、次のアクションを完了する方法について説明します。

  • MongoDBと連携するために Lambdaプロジェクトを構成する

  • タスクスケジューラーのCRUD機能を実装する

  • トリガー システム用のカスタム Lambda アーティサンド コマンドを作成する

  • タスクをスケジュールしてアーティザ コマンドを間隔ごとに実行する

  • Linux ベースのサーバーで cronジョブを構成する

このチュートリアルで説明されている概念をさらに学ぶには、次のリソースを参照してください。

  • 使用例 一般的な操作のコード例について

  • 効率モデルを操作するための効率モデル

戻る

コマンドの実行