ポートフォリオに実装する簡単ログイン機能を実装したので、備忘録として書いていきます。
Laravelがそんなに記事数なかったので参考になれば喜びます。(Railsの記事は沢山あった。。。)
実装内容
seedでゲストユーザーを作成し、ゲストボタンクリックでゲストユーザーとしてログイン出来る様にする。
ゲストユーザーが出来ない事は、emailやpassword、nameなどの情報の編集は行えない様にする。
テストも行う。
前提
前提というか、メール、パスワードの編集機能制限部分で編集機能の実装についてはこちらの記事で書いているので是非確認してみてください。このを参考にしています。
大まかな実装手順
seedファイル作成、編集
ルーティング追加
コントローラー処理追加
viewファイルボタン追加
ログイン確認
情報編集制限
viewファイル編集
コントローラー編集
テスト
こんな感じで書いていきます。
seedファイル作成、編集
php artisan make:seed ファイル名
ユーザーのシードファイルはすでに存在するので上記のコマンドは必要なしです。ファクトリーのファイルも同じ考え方です。
use App\User;
use App\Tel;
use App\Address;
public function run()
{
// テストユーザーの作成
1 test_user = factory(User::class)->create(['name' => 'テストユーザー', 'email' => 'test@test.com']);
// ユーザーに直接紐付くテーブルを作成する。
$test_user->address()->save(factory(Address::class)->create(['user_id' => $test_user->id]));
$test_user->tel()->save(factory(Tel::class)->create(['user_id' => $test_user->id]));
}
1, テストユーザーを作成する時に、create()メソッドに引数を渡している。
ルーティング追加
postアクションで設定します。
// ゲストログイン
1 Route::post('/login/guest', 'Auth\LoginController@guestLogin')->name('guest_login');
1, ログインするだけなのでこれだけです。
コントローラー処理追加
ログイン処理を書きます。
public function guestLogin()
{
1 if (Auth::attempt(['email' => 'test@test.com', 'password' => 'Test1234'])) {
2 return redirect()->route('home')->with('say', 'テストユーザーとしてログインしました!');
} else {
return false;
}
}
1, Auth::attempt()メソッドを使ってテストユーザーでログインします。
2, ログインした後はホームにリダイレクトさせます。
viewファイルボタン追加
ゲストユーザーのログインボタン作成です。
<form method="POST" action="{{ route('guest_login') }}"> 1
@csrf 2
<button type="submit" class="btn btn-success ml-2">
{{ __('Guest Login') }}
</button>
</form>
1, ログインボタンはpostメソッドとroute名を記載します。route名についてはphp artisan route:listで確認出来ます。
2, @csrfも忘れない様に。これがないとエラーが出ます。
ログイン確認
上記が書けたらサーバー再起動して、ゲストユーザーログイン出来るか確認しましょう!
viewファイル編集
条件分岐でemail編集ページにアクセス出来ない様にします。
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('メール') }}</label>
<div class="col-md-6">
1 @if(Auth::User()->email != 'test@test.com')
2 <a href="{{ route('emailchange_before', ['user' => $user->id] ) }}"><p style="margin-top: .4rem;">メールアドレスを変更する</p></a>
@else
<small class="text-muted">テストユーザーのメールアドレス変更は出来ません</small>
@endif
</div>
</div>
1, テストユーザーであるかどうかの条件分岐をしています。
2, テストユーザーはこのリンクにアクセス出来ません。
コントローラー編集
先ほどの条件分岐だけだと、urlを直接入力されるとアクセス出来てしまいます。なのでコントローラーでも条件分岐です。
public function emailchange_show(User $user)
{
1 $check_user = Auth::user();
2 if($check_user->id == $user->id && $check_user->email != 'test@test.com') {
return view('users.emailchange')->with('user', $user);
} else {
3 abort(403);
}
}
1, 現在ログインしているユーザーを取得します。
2, 取得したユーザーがテストユーザーかどうか確認している。
3, テストユーザーであれば、403エラー(権限が無い)をabortで返す。
テスト
編集ページに遷移出来ないことを確認します。パスワードについてはほぼ同じなので省略しています。
テストについては適宜追加してください。
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\User;
use Artisan;
class GuestUserTest extends TestCase
{
use RefreshDatabase;
1 public function setUp(): void
{
parent::setUp();
// 毎回seedでデータベースが作られるのでテスト毎にデータベースをリセットしている
2 Artisan::call('migrate:fresh');
// シーダー実行
3 $this->seed('UserTableSeeder');
// テストユーザーを取得、定義する
4 $this->user = User::where('email', 'test@test.com')->first();
}
// 異常系
public function test_Email編集画面にログインしていても遷移出来無い()
{
5 $response = $this->actingAs($this->user);
$response = $this->get(route('emailchange_before', ['user' => $this->user->id]));
6 $response->assertStatus(403);
}
public function test_Password編集画面にログインしていても遷移出来無い()
{
$response = $this->actingAs($this->user);
$response = $this->get(route('passwordchange_before', ['user' => $this->user->id]));
$response->assertStatus(403);
}
}
以下コマンドで実行
7 vendor/bin/phpunit --testdox
1, この中にテストの前に実行する処理を書きます。1テスト毎に実行されます。
2, データベースのリセットコマンドを実行して重複を防ぐ。
3, seedを実行してデータベースにテストユーザーを保存します。
4, テストユーザーを取得して定義します。
5, テストユーザーをログイン状態にします。
6, 編集ページにアクセスした時にステータスが403になっていることを確認します。
7, –testdoxオプションを付ける事でどのテストを実行しているのか確認できます。参考記事
課題
emailやpasswordの編集の制限方法
guardやgate機能を使えると良いのか?と思うところです。けどそうなるとseedで作るテストユーザーを違うタイプのユーザーとして認識させる(adminとかそっち系の)必要ありそうだな〜とか考えると。。。。って感じで今回の実装方法にしました。w
まとめ
個人的には実装したい部分については出来たので良しとしていますが、他にもやり方がある場合は教えて頂けると嬉しいです〜!
今回はこんな感じで!
以上!