こんにちは!
PHPのLaravelやJavaScriptでWeb開発をしているフリラーンスエンジニアのファドと申します!
こちらの記事は応用Laravel教材の第3回目の記事になります。
その他の応用Laravel教材を学習したい方は下記リンクから直接教材へ飛ぶことができます。
-
応用Laravel
【応用Laravel教材①】タスク管理アプリを実装してLaravelをより深く知る!〜環境構築からログイン機能実装編〜
-
応用Laravel
【応用Laravel教材②】Laravelでタスク管理アプリ実装!〜テンプレートの作成からログイン画面作成編〜
-
応用Laravel
【応用Laravel教材④】Laravelでタスク管理アプリ実装!〜タスク一覧機能実装編〜
-
応用Laravel
【応用Laravel教材⑤】Laravelでタスク管理アプリ実装!〜プロジェクト追加機能実装からタスク追加機能実装編〜
-
応用Laravel
【応用Laravel教材⑥】Laravelでタスク管理アプリ実装!〜タスク編集機能実装編〜
プロジェクト一覧
次はプロジェクト一覧画面を作成していきましょう。
ルーティング
まずはルーティングから行っていきます。task-app/routes/web.php
を下記の通り編集してください。
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProjectController;
Route::get('/', function () {
return view('welcome');
});
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');
// ログイン必須ルート
Route::middleware('auth')->group(function () {
// プロジェクト一覧画面
Route::get('projects', [ProjectController::class, 'index'])->name('projects.index');
});
require __DIR__.'/auth.php';
まず、タスク管理アプリには、未ログインユーザーがアクセスできないページがいくつか存在しています。
その内の一つが今回実装するプロジェクト一覧画面です。web.php
では、アプリケーションの利用に認証を求める機能を実装することができます。
ページに認証を求める処理はミドルウェアを用いて実装します。
ミドルウェアとは、ルート毎の処理に移る前に実行される処理のことです。
つまり、画面を表示する前にログインかどうかをミドルウェアを使用して確かめるということです。
認証を求めるミドルウェアは最初から用意されているので、ルートにミドルウェアを適用するだけで実装することができます。
具体的な記述方法は下記の通りです。
Route::middleware('auth')->group(function () {
// ここにログイン後しか表示できないルートを記述する
});
とても簡単ですね。
以降ログインが必要な画面・処理のルーティングをする場合は、この中に記述していきます。
今はこれから実装するプロジェクト一覧画面のルーティングを記述しています。
コントローラー作成&編集
次に、ルーティングで指定したProjectコントローラー
を作成していきます。
ターミナルで下記コマンドをtask-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan make:controller ProjectController
作成が完了したら、task-app/app/Http/Controllers/ProjectController.php
を下記の通り編集してください。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProjectController extends Controller
{
/**
* プロジェクト一覧画面表示
*/
public function index()
{
return view('projects.index');
}
}
これでProjectコントローラー
にindexメソッド
を作成することができました。http://localhost/projects
にアクセスがあった場合、projects/index.blade.php
を表示させるように処理を記述したので、index.blade.php
を作成していきましょう。
まずはtask-app/resources/views
ディレクトリ配下にprojects
フォルダを作成してください。
作成が完了したらprojects
フォルダ内にindex.blade.php
を作成してください。
コマンドで作成する場合は、ターミナルで下記コマンドをtask-app
ディレクトリ上で実行してください。
$ mkdir resources/views/projects && touch resources/views/projects/index.blade.php
作成したtask-app/resources/views/projects/index.blade.php
を下記の通り編集してください。
@extends('layouts.layout')
@section('title')
プロジェクト一覧
@endsection
@section('content')
<div class="container mt-4">
<div class="row">
<div class="col col-md-6 offset-md-3">
<div class="card">
<div class="card-header bg-dark text-light d-flex justify-content-between align-items-center">
<p class="mb-0 h5">プロジェクト</p>
<a href="#" class="btn btn-primary">追加</a>
</div>
<table class="table table-hover mb-0">
<tbody class="text-center">
<tr>
<td class="table-active"><a href="#">プロジェクト1</a></td>
</tr>
<tr>
<td><a href="#">プロジェクト2</a></td>
</tr>
<tr>
<td><a href="#">プロジェクト3</a></td>
</tr>
<tr>
<td><a href="#">プロジェクト4</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection
今回は特に難しい記述はありません。
まだプロジェクトのデータが存在していないので、HTMLでデータ部分を記述しています。
テーブル作成
プロジェクトのデータを保存するためのprojectsテーブルを作成していきます。
projectsテーブルの内容は下記の通りです。
カラム名 | 日本語 |
---|---|
id | ID |
user_id | ユーザーID |
project_name | プロジェクト名 |
created_at | 作成日 |
updated_at | 更新日 |
user_id
というカラムが存在していますが、このカラムの値とusersテーブル
のid
を紐付けることで、どのユーザーが作成したプロジェクトなのかをデータとして紐付けることができます。
それでは、さっそくマイグレーションでprojectsテーブル
を作成していきましょう。
ターミナルで下記コマンドをtask-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan make:migration create_projects_table
作成したtask-app/database/migrations/2022_06_23_223330_create_projects_table.php
を下記の通り編集してください。
※2022_06_23_223330は作成した日時なので、皆さんのファイルとは異なっています。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id')->unsigned(); // ここを追加
$table->string('project_name', 30); // ここを追加
$table->timestamps();
// 外部キーの設定
$table->foreign('user_id')->references('id')->on('users'); // ここを追加
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('projects');
}
};
追加した内容を確認すると、外部キーの設定という処理が追加されています。
これは2つのテーブル間でデータの整合性を保つために設定される制約です。
必須の設定ではありませんが、usersテーブル
とprojectsテーブル
のデータの整合性を保つために記述しておきます。
※データの整合性を保つ例としては、ユーザー情報が削除されると、削除されたユーザーに紐付いたプロジェクト情報も削除されます。
では、ターミナルで下記コマンドをtask-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan migrate
これでprojectsテーブル
が作成されました。
モデル作成
次に、projectsテーブル
のデータを操作するためのモデルを作成しましょう。
ターミナルで下記コマンドをtask-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan make:model Project
作成したtask-app/app/Models/Project.php
を下記の通り編集してください。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'project_name',
];
}
データ内容を変えたいカラムを$fillable
で指定しておきましょう。
今回はユーザーID
とプロジェクト名
の2つのカラムのみでOKです。
テストデータ作成
モデルの作成も終わったので、シーダーを使用してテストデータを作成していきましょう。
ターミナルで下記コマンドをtask-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan make:seeder ProjectsTableSeeder
作成したtask-app/database/seeders/ProjectsTableSeeder.php
を下記の通り編集してください。
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB; // ここを追加
class ProjectsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// usersテーブルから1つのデータを取得
$user = DB::table('users')->first();
DB::table('projects')->insert([
'project_name' => 'プロジェクト1',
'user_id' => $user->id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
DB::table('projects')->insert([
'project_name' => 'プロジェクト2',
'user_id' => $user->id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
DB::table('projects')->insert([
'project_name' => 'プロジェクト3',
'user_id' => $user->id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
}
}
特に難しい処理はしていません。
今回はテストデータとして3つのデータを作成しました。
また、user_id
には、存在するuser_id
が保存されていてほしいので、$user = DB::table('users')->first();
と記述して、シーダーファイル内でユーザー情報を取得するようにしています。
次にtask-app/database/seeders/DatabaseSeeder.php
を下記の通り編集してください。
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call([
UsersTableSeeder::class,
ProjectsTableSeeder::class,
]);
}
}
これでprojectsテーブル
のテストデータを作成する準備が整いました。
それでは、ターミナルで下記コマンドをtask-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan migrate:refresh --seed
今回は新しくシーダーファイルを追加したので、migrate:refresh
コマンドを実行します。
このmigrate:refresh
コマンドを実行すると、全てのテーブルが一回削除され、もう一度マイグレーションが実行されます。
つまり、中のデータもリセットされるということです。
また、--seed
オプションを付けると、シーダーの実行も一緒にしてくれるので、テーブルの作成とデータの作成を同時に行ってくれます。
migrate:refresh
コマンド後にテーブルのデータを確認しておくといいですね!
リレーション
次はリレーションを定義していきます。
そもそもリレーション
とは、データベース上のテーブルを関連付けるための機能です。
例えば今回の実装の場合、usersテーブル
とprojectsテーブル
の2つが存在しています。
外部キーの設定でも少し説明しましたが、この2つのテーブルはid
とuser_id
で関連付けられています。
これをLaravelでは、どのテーブルとどのテーブルが関連しているのかをモデルの中に定義することができます。
リレーションにはいくつかの種類があり、代表的なものを2つ紹介します。
リレーション | メソッド | 例 |
---|---|---|
1 対 1 | hasOne() | 1人のユーザーに対してプロフィール画像は1枚 |
1 対 1(逆) | belongsTo() | 1枚のプロフィール画像に対してユーザーは1人 |
1 対 多 | hasMany() | 1人のユーザーに対して投稿は複数 |
1 対 多(逆) | belongsTo() | 1つの投稿に対してユーザーは1人 |
リレーションでは、このようにどのテーブルとどのテーブルがどのような関係で関連しているのかを定義することができます。
リレーションを設定していると、下記のような利点があります。
- リレーション先のテーブルにあるデータを取得できる
- テーブル情報に変更があれば、自動的に変更があったテーブルとリレーションのあるテーブルにも情報が反映される
なんとなくイメージはできたと思うので、さっそく実装していきます。
task-app/app/Models/User.php
を下記の通り編集してください。
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* 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',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
// --- ここから追加 ---
/**
* Projectsテーブルとのリレーション
*/
public function projects()
{
return $this->hasMany(Project::class);
}
// --- ここまで追加 ---
}
今回は$this->hasMany(Project::class);
と定義しています。
それは、1人のユーザーに対して複数のプロジェクトを保持することができるからです。
また、メソッド名はprojects
と複数形にしています。
これも複数のプロジェクトを保持できることから複数形にしています。
projectsテーブル
から見た時のリレーションも設定していきましょう。task-app/app/Models/Project.php
を下記の通り編集してください。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
use HasFactory;
protected $fillable = [
'project_name',
'user_id',
];
// --- ここから追加 ---
/**
* Usersテーブルとのリレーション
*/
public function user()
{
return $this->belongsTo(User::class);
}
// --- ここまで追加 ---
}
今回は$this->belongsTo(User::class);
と定義しています。
それは、1つのプロジェクトに対して、1人のユーザーがそのプロジェクトの所有者だからです。
また、メソッド名はuser
と単数形にしています。
これは1つのプロジェクトにつき、プロジェクトの保有者は1人だからです。
これで定義自体は終わりです。
定義したメソッドの使用方法は実装時に確認しましょう。
コントローラー編集
プロジェクトのテストデータを用意したので、projectsテーブル
からデータを取得して表示できるようにしてみましょう。
task-app/app/Http/Controllers/ProjectController.php
を下記の通り編集してください。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; // ここを追加
class ProjectController extends Controller
{
/**
* プロジェクト一覧画面
*/
public function index()
{
// ログインユーザーが作成した全てのプロジェクトを取得
$projects = Auth::user()->projects->all();
return view('projects.index', compact('projects'));
}
}
Laravelでは現在のログインユーザー情報をAuth::user()
と記述することで取得することができます。
これはLaravelのAuthファサード
という機能を使用することで実装することができるので、use文
を使用して、Authファサード
を読み込んでいます。
また、ユーザー情報に->projects->all()
と記述するとリレーション先のprojectsテーブル
の情報を取得することができます。
ここで先ほどUserモデル
に定義したprojectsメソッド
を使用することができるということです。
後は取得したプロジェクト情報をcompact関数
を使用してビューに渡しています。
ビュー編集
次はビューを編集していきましょう。task-app/resources/views/projects/index.blade.php
を下記の通り編集してください。
@extends('layouts.layout')
@section('title')
プロジェクト一覧
@endsection
@section('content')
<div class="container mt-4">
<div class="row">
<div class="col col-md-6 offset-md-3">
<div class="card">
<div class="card-header bg-dark text-light d-flex justify-content-between align-items-center">
<p class="mb-0 h5">プロジェクト</p>
<a href="#" class="btn btn-primary">追加</a>
</div>
<table class="table table-hover mb-0">
<tbody class="text-center">
@foreach ($projects as $project)
<tr>
<td><a href="#">{{ $project->project_name }}</a></td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection
http://localhost/projectsにアクセスし、下記画像のような画面が表示されればOKです。
これでプロジェクト一覧が表示されるようになりました。
新規登録・ログイン後のリダイレクト先を変更
現在、新規登録・ログイン後にリダイレクトされる先は下記の通りです。
これを先ほど作成したプロジェクト一覧に遷移するように設定しましょう。
Laravel Breezeでログイン機能を実装した場合、新規登録・ログイン後のリダイレクト先を変更するには、RouteServiceProvider.php
のpublic const HOME = '/dashboard'
を変更する必要があります。
task-app/app/Providers/RouteServiceProvider.php
を下記の通り編集してください。
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/
public const HOME = '/projects';
// --- 以下省略 ---
}
編集が終了したら、http://localhost/loginからログインしてください。
ログイン後のリダイレクト先が下記画像のようにプロジェクト一覧画面になっていればOKです。
定数HOME
にプロジェクト一覧のパス
を指定することで、指定したリダイレクト先にリダイレクトされるようになります。
これは新規登録処理のコントローラーRegisteredUserController.php
とログイン処理のコントローラーAuthenticatedSessionController.php
のstoreメソッド
の中身で、RouteServiceProvider
の定数HOME
がリダイレクト先として指定してあるからです。
RegisteredUserController.php
のstoreメソッド
は下記の通りです。
public function store(Request $request)
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
return redirect(RouteServiceProvider::HOME);
}
return redirect(RouteServiceProvider::HOME);
と記述されているのがわかると思います。
また、AuthenticatedSessionController.php
のstoreメソッド
は下記の通りです。
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
}
return redirect()->intended(RouteServiceProvider::HOME);
と記述されています。
中身の処理をわざわざ覚える必要は全くありません。
リダイレクト先の変更はRouteServiceProvider.php
の定数HOME
を変更することで実装できることが理解できればOKです!
念の為、新規登録後のリダイレクト先もプロジェクト一覧になっているかも各自確かめておきましょう。
次の教材
次の教材は下記から簡単に飛ぶことができます!
引き続きプログラミングを楽しんでいきましょう!
プログラミング学習サポートについて
「独学で挫折した。。。」
「一人でのプログラミング学習がしんどい。。。」
「未経験からエンジニア転職をしたいけど何をしたら良いかわからない。。。」
このような悩みをお持ちの方向けに、本教材作成者のファドがMENTAという学習サイトにてあなたのプログラミング学習とエンジニア転職を徹底サポートいたします!
サポート価格はなんと1日あたりたったの約300円!
教材で分からない箇所のサポートはもちろんのこと、本サイトで公開しているすべての課題の解答も公開しております。
また、MENTAで学習を終わらせていただいた方限定で懇意にしていただいている企業さんを紹介することもあります!
なお、サポート内容の詳細は下記の通りです。
- 目標設定
- マインドセット
- オリジナル教材見放題
- オリジナル課題見放題
- オリジナル課題の解答見放題
- 課題コードレビュー
- 教材への無制限質問
- 課題への無制限質問
- ポートフォリオ作成アドバイス
- 褒めのコーチング
いくつかのプランを用意させていただいておりますので、下記より一度ご覧ください!
コメント