皆さんこんにちは!
この記事は、「Laravel + Vueでtrello風タスク管理アプリを作ろう!!」の2回目になります。
前回の、準備編を見ていない方は、先にそちらを確認して下さい。
早速ですが、前回の続きに入りたいと思います。
もくじ
テーブル作成

今回作成するアプリケーションでは、次の様なデータを保存する必要があります。
今回は、「tasks」「statuses」という名前で2つテーブルを作成します。
「tasks」は、付箋側で、「statuses」はボード側を表します。
タスク「tasks」
- タイトル—タスクのタイトルが必要です。
- 説明—タスクの追加詳細
- 順序—列のどこにあるかを保存し再現するために利用します。
- ステータスID —タスクの現在どのステータスに属しているかを判定するため必要です。
- ユーザーID —今回は、複数のユーザーで管理するボードを作るわけでは無いので、個人を特定するために保存します。
ステータス「statuses」
- タイトル-ボード自体にもタイトルが必要です。
- スラッグ-キーなどに使用するために用意。(クライアント側で使います。)
- 順序-ステータスの順序を定義します。
- ユーザーID —今回は、複数のユーザーで管理するボードを作るわけでは無いので、個人を特定するために保存します。
今回利用するテーブルは、上の2つの他、Laravel標準で用意されているUsersテーブルも利用します。
テーブル作成で重要な、データ間の繋がりのポイントは以下の内容です。
・1人のユーザーは、複数のステータス(ボード列)を持つ
・1人のユーザーは、複数のタスク(付箋)を持つ
・1つのステータス(ボード列)は、複数のタスク(付箋)を持つ
説明が長くなってすみません。
早速始めていきたいと思います!
モデルとマイグレーションの作成
ターミナルまたはコマンドプロンプトでプロジェクトディレクトリーへ移動して、次のコマンドを実行して下さい。
今回は、あとで必要になるので、「コントローラー」も併せて作成しておきます。
php artisan make:model -mc Task
php artisan make:model -mc Status
オプションに「-mc」を付与する事で、モデル、マイグレーションファイル、コントローラが作成されます。
マイグレーションファイルの編集
先ほど実行したコマンドで、マイグレーションファイルの雛形が出来上がっているので、以下のファイルをエディタで開いて次の様に編集して下さい。
※upメソッドのみ編集すれば、良いです。
database/migrations/XXXX_create_tasks_table.php
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description')->nullable();
$table->smallInteger('order')->default(0);
$table->unsignedInteger('user_id');
$table->unsignedInteger('status_id');
$table->timestamps();
});
}
database/migrations/XXXX_create_statuses_table.php
public function up()
{
Schema::create('statuses', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug');
$table->smallInteger('order')->default(0);
$table->unsignedInteger('user_id');
$table->timestamps();
});
}
マイグレーションファイルの編集が終わったら、マイグレーションを実行してデータベースへ反映させます。
php artisan migrate
テーブルが作成できたかどうかは、「phpMyAdmin」やターミナル上から、確認してみて下さい。
※Laravelのプロジェクトを作成した段階で用意されているマイグレーションファイルも同時に実行されるので、他のテーブルもできていますが、問題はありません。
モデルの編集
テーブル同士を関連づけるために、各モデルを編集します。
また、save()メソッドで保存するレコードの定義も併せて行います。
app/User.php
class User extends Authenticatable
{
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function tasks()
{
return $this->hasMany(Task::class);
}
public function statuses()
{
return $this->hasMany(Status::class)->orderBy('order');
}
}
app/Task.php
class Task extends Model
{
protected $fillable = [‘title’, ‘description’, ‘order’, ‘status_id’];
public function user()
{
return $this->belongsTo(User::class);
}
public function status()
{
return $this->belongsTo(Status::class);
}
}
app/Status.php
class Status extends Model
{
protected $fillable = [‘title’, ‘slug’, ‘order’];
public $timestamps = false;
public function tasks()
{
return $this->hasMany(Task::class)->orderBy('order');
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Eloquentのリレーション(関係)は、Eloquentモデルクラスのメソッドとして定義します。
詳しくは、公式ドキュメントを、参照して下さい。
ルーティングとコントローラーの編集
今回、必要となるルートを全て定義しておきます。
今回は「routes/web.php」に全てのルート定義を記述します。
Route::get('/', function () {
if (Auth::user()) {
return redirect()->route('home');
}
return redirect('/login');
}); //welcomeへ向いているので、変更して下さい。
Auth::routes(); //既にあるはず
Route::get('/home', function () {
return redirect()->route('tasks.index');
})->name('home');
Route::group(['middleware' => 'auth'], function () {
Route::get('tasks', 'TaskController@index')->name('tasks.index');
Route::post('tasks', 'TaskController@store')->name('tasks.store');
Route::put('tasks/sync', 'TaskController@sync')->name('tasks.sync');
Route::delete('tasks/{tasks}', 'TaskController@destroy')->name('tasks.destroy');
});
Route::group(['middleware' => 'auth'], function () {
Route::post('statuses', 'StatusController@store')->name('statuses.store');
Route::put('statuses/sync', 'StatusController@sync')->name('statuses.sync');
Route::delete('statuses/{status}', 'StatusController@destroy')->name('statuses.destroy');
});
今回作成するアプリケーションに必要な機能は、このルート定義を見れば掴めるかと思います。
以下のコマンドをターミナルで実行する事で、全てのルートを確認する事ができます。
php artisan route:list
ルーティングに関しての詳細な説明は省略します。
詳しくは、公式ドキュメントを、参照して下さい。
トップページ用のアクションを定義する
トップページを返すルートは以下のものになります。
Route::get('tasks', 'TaskController@index')->name('tasks.index');
http://localhost:8000/tasksへ、Getでリクエストを受けたらTaskControllerのindex()メソッドを実行する、という流れを記述してあります。
それでは、TaskControllerをエディタで開き、次の様に追記して下さい。
app/Http/Controllers/TaskController.php
class TaskController extends Controller
{
// ここから
public function index()
{
$tasks = auth()->user()->statuses()->with('tasks')->get();
return view('tasks.index', compact('tasks'));
}
// ここまで
}
簡単に説明すると、「tasks/index.blade.php」へ「$tasks」という変数に入れた、データを渡す、という処理になります。
$tasksはデータベースから取得したデータが、Eloquentモデルとして入っています。
Viewの作成
それでは、画面を作りたいと思います。
今回は、デザインやBladeテンプレートについての説明は省略します。
「resources/views/」に、新たに「tasks」ディレクトリを作成して下さい。
さらにそのディレクトリ内に、「index.blade.php」を作成して、エディタで開き、下記の様に編集します。
resources/views/tasks/index.blade.php
@extends('layouts.app')
@section('content')
<div class="md:mx-4 relative overflow-hidden">
<main class="h-full flex flex-col overflow-auto">
</main>
</div>
@endsection
お疲れ様です。
これで、カンバンを作るための土台が全て出来上がりました。
デフォルトステータスボード
もし、ユーザー登録時にデフォルトでステータスの列を追加する様にしたい場合、次のコードをUser.phpへ記載しておくと良いです。
ユーザー作成時に、自動的にデータベースへレコードが挿入されます。
app/User.php
protected static function booted()
{
static::created(function ($user) {
$user->statuses()->createMany([
[
'title' => '未処理',
'slug' => 'backlog',
'order' => 1
],
[
'title' => '着手',
'slug' => 'up_next',
'order' => 2
],
[
'title' => '進行中',
'slug' => 'progress',
'order' => 3
],
[
'title' => '完了',
'slug' => 'done',
'order' => 4
],
[
'title' => '保留',
'slug' => 'on_hold',
'order' => 5
]
]);
});
}
まとめ
いかがだったでしょうか?
次回は、Vue.jsの部分(クライアントサイド)を作成したり、APIの処理を記述したりしていきます。
次回から、ブラウザーで確認しながらコードを書いていくので楽しくなってくると思います。
最後まで読んでいただいてありがとうございます。
これからもよろしくお願いします!!