### デフォルト設定
– 試行回数: 5回
– ロック時間 : 45 seconds

app/Http/Controllers/Auth/LoginController.php
protected $maxAttempts = 5; protected $decayMinutes = 5;

▼ログイン機能の実装
/vendor/laravel/framework/src/Illuminate/Foundation/Auth/ThrottlesLogins.php
随机应变 ABCD: Always Be Coding and … : хороший
### デフォルト設定
– 試行回数: 5回
– ロック時間 : 45 seconds

app/Http/Controllers/Auth/LoginController.php
protected $maxAttempts = 5; protected $decayMinutes = 5;

▼ログイン機能の実装
/vendor/laravel/framework/src/Illuminate/Foundation/Auth/ThrottlesLogins.php
### メール本文テンプレート作成
resources/views/mail/passwordreset.blade.php
<body>
<h1>パスワードリセット</h1>
<p>以下のボタンを押下し、パスワードリセットの手続きを行ってください。</p>
<p id="button">
<a href="{{ $reset_url }}">パスワードリセット</a>
</p>
</body>
### 通知クラス
$ php artisan make:notification PasswordResetNotification
app/Notifications/PasswordResetNotification.php が生成される
public $token;
protected $title = 'パスワードリセット通知'
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct($token)
{
//
$this->token = $token;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
//テンプレートとテンプレートに渡す引数
public function toMail($notifiable)
{
return (new MailMessage)
->subject($this->title)
->view(
'mail.passwordreset',
[
'reset_url' => url('password/reset', $this->token),
]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
### User.php
use App\Notifications\PasswordResetNotification;
public function sendPasswordResetNotification($token){
$this->notify(new PasswordResetNotification($token));
}
sendPasswordResetNotificationのオーバーライドはcontrollerではなく、Userモデルで行う。
デフォルトだとログアウト処理では、’/'(ルート)に遷移する
### view
<form id="logout-form" action="{{ route('logout') }}" method="POST" name="logout">
@csrf
<a href="javascript:document.logout.submit()">ログアウト</a>
</form>
### LoginController.php
app/Http/Controllers/Auth/LoginController.php
->/hogeに遷移
use Illuminate\Support\Facades\Auth;
public function logout(Request $request){
Auth::logout();
$this->guard()->logout();
$request->session()->invalidate();
return $this->loggedOut($request) ?: redirect('/hoge');
}
# 初期
### usersにlast loginカラムを追加
mysql> describe users;
$ php artisan make:migration add_column_last_login_at_users_table –table=users
***_add_column_last_login_at_users_table.php
public function up()
{
Schema::table('users', function (Blueprint $table) {
//
$table->timestamp('last_login_at')->nullable()->after('remember_token')->comment('最終ログイン');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
//
$table->dropColumn('last_login_at');
});
}
$ php artisan migrate
mysql> describe users;
### Logined eventとLastLoginListeners listenerを作成
app/Providers/EventServiceProvider.php
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
// ログイン時にイベント発行
'App\Events\Logined' => [
// 最終ログインを記録するリスナー
'App\Listeners\LastLoginListener',
],
];
$ php artisan event:generate
### listenerで、lastlogin日時をDBに保存する
– event側は処理なし
app/Listeners/LastLoginListener.php
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
public function handle(Logined $event)
{
//
$user = Auth::user();
$user->last_login_at = Carbon::now();
$user->save();
}
### LoginControllerでeventを呼び込む
app/Http/Controllers/Auth/LoginController.php
use Illuminate\Http\Request;
use App\Events\Logined;
protected function authenticated(Request $request, $user)
{
event(new Logined());
}
mysql> select * from users;
+—-+———+————–+——————+——————-+————————————————————–+————————————————————–+———————+———————+———————+
| id | role_id | name | email | email_verified_at | password | remember_token | last_login_at | created_at | updated_at |
+—-+———+————–+——————+——————-+————————————————————–+————————————————————–+———————+———————+———————+
| 1 | 1 | 田中太郎 | tanaka@***.com | NULL | **** | **** | 2020-02-21 09:50:03 | 2020-02-20 08:51:14 | 2020-02-21 09:50:03 |
| 2 | 2 | 山田一郎 | yamada@***.com | NULL | **** | **** | NULL | 2020-02-20 08:52:15 | 2020-02-20 08:52:15 |
+—-+———+————–+——————+——————-+————————————————————–+————————————————————–+———————+———————+———————+
2 rows in set (0.00 sec)
公式ドキュメント:https://readouble.com/laravel/6.x/ja/authentication.html
middlewareが複数ある場合は、ブランケットで配列にして渡す
Route::group(['middleware' => ['auth','IsAdmin'] ], function(){
Route::get('/admin/', 'AdminController@index');
});
Route::group(['middleware' => ['auth', 'IsSubscriber']], function(){
Route::get('/', 'SubscriberController@index');
});
Route::group(['middleware' => 'auth'], function(){
Route::get('/create', 'SubscriberController@create');
});
controllerが読み込まれる前に処理するか、controllerのconstructorで処理するかの違いだが、どちらでも動くには変わりないが、指定するmiddlewareの機能や、CPUのレジストリ処理の特性を考えると、controller側よりもルーティングで指定した方が効率が良いと考えられる。
– exceptで除外するメソッドを指定する
public function __construct(){
$this->middleware('IsSubscriber')->except('create');
}
public function index(Request $request)
{
//
$user = Auth::user();
return view('subscriber.index', compact('user'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
$user = Auth::user();
return view('subscriber.create', compact('user'));
}
# 前準備
### 6系のmake:auth
$ php composer.phar require laravel/ui
$ php artisan ui vue –auth
### usersテーブルとuser_idにbelongsToのrolesテーブル
$ php artisan make:model Role -m
create_users_table
-> role_idは便宜上、nullableにしておく
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('role_id')->nullable();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
create_roles_table
Schema::create('roles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
$ php artisan migrate
mysql> insert into roles (name) values (‘administrator’);
mysql> insert into roles (name) values (‘subscriber’);
### font end
$ npm install
$ npm run dev
### ユーザーデータ作成
$ php artisan serve –host 192.168.33.10 –port 8000
// ユーザ作成
http://192.168.33.10:8000/register
->田中太郎(‘administrator’)
->山田一郎(‘subscriber’)
// role_idを付与
mysql> update users set role_id=1 where id=1;
mysql> update users set role_id=2 where id=2;
mysql> select * from users;
ここまでは大体、10~15分位
# auth認証
### middleware作成
$ php artisan make:middleware IsAdmin
app/Http/Kernel.php
protected $routeMiddleware = [
//省略
'IsAdmin'=>\App\Http\Middleware\IsAdmin::class,
];
### Userモデルで権限判定処理
User.php
public function IsAdmin(){
if($this->role->name == 'administrator'){
return true;
}
return false;
}
Route
Route::get('/', function () {
// return view('welcome');
$user = Auth::user();
if($user->IsAdmin()){
echo "this user is administartor";
}
});
### middlewareの処理
app/Http/Middleware/IsAdmin.php
-> adminでなければtopにリダイレクト
use Illuminate\Support\Facades\Auth;
public function handle($request, Closure $next)
{
$user = Auth::user();
if(!$user->isAdmin()){
return redirect()->intended('/');
}
return $next($request);
}
$ php artisan make:controller –resource AdminController
$ php artisan make:controller –resource SubscriberController
### route
Route::group(['middleware' => 'auth'], function(){
Route::get('/admin/', 'AdminController@index');
Route::get('/', 'SubscriberController@index');
});
### admin, subscriberのview作成
resources/views/admin/index.blade.php
resources/views/subscriber/index.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
this is {{ $user->role->name }}, {{ $user->name }}<br>
<form id="logout-form" action="{{ route('logout') }}" method="POST" name="logout">
@csrf
<a href="javascript:document.logout.submit()">ログアウト</a>
</form>
</body>
</html>
### controller
AdminController
public function __construct(){
$this->middleware('IsAdmin');
}
public function index()
{
//
$user = Auth::user();
return view('admin.index', compact('user'))
}
### ログイン後のリダイレクト先の変更
app/Http/Middleware/RedirectIfAuthenticated.php
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
// return redirect(RouteServiceProvider::HOME);
return redirect('/admin');
}
return $next($request);
}
app/Http/Controllers/Auth/LoginController.php
app/Http/Controllers/Auth/RegisterController.php
app/Http/Controllers/Auth/ResetPasswordController.php
protected $redirectTo = '/admin';
これだと、administratorは、’/admin’, ‘/’ 両方アクセスできるので、IsSubscriberのMiddlewareを作らないと駄目か。
subscriberの挙動は期待通りになる。
### view
<template v-for="m in messages>
// 省略
<span>@{{ m.created_at | moment }}</span>
// 省略
</template>
### script
– Vueのmethods内でmoment()を呼び出し、filtersでformatを指定する
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js" type="text/javascript"></script>
<script>
new Vue({
el: '#app',
filters: {
moment: function (date) {
return moment(date).format('MM/DD HH:mm');
}
},
data: {
// 省略
},
methods: {
// 省略
moment: function () {
return moment();
}
},
mounted(){
// 省略
}
});
</script>
momentはvueの中で指定しないとうまく動かない。
make:resourceでサーバ側でcarbonで整形することも考えたが、コントローラの処理が複雑な為、クライアント側でフォーマット化する。
## Messageモデル
– usersテーブルに対し、messagesテーブルがbelongsToのリレーション関係
public function user(){
return $this->belongsTo('App\User');
}
## controller
$messages =Message::where(function($q) use ($foo, $hoge){
// 省略
})->orderBy('***','ASC')->get();
### 通常時のblade
– $message->user->name で名前を呼び出す
@foreach($messages as $message)
// 省略
{{ $message->user ? $message->user->name : '削除済ユーザ' }}
// 省略
@endforeach
# Vue.js使用時
## controller
– with(‘user’)でユーザテーブルの情報も取得する
return Message::with('user')->where(function($q) use ($foo, $hoge){
// 省略
})->orderBy('***','ASC')->get();
## blade
– vueで表示する際は、m.user.name と書く
<div v-for="m in messages"> // 省略 <span v-text="m.user.name"></span> // 省略 </div>
belongsToもVueで表示できるのか!? 表示できないなら、Vueは断念しようかと思ってた。
## laravel bladeでの三項演算子
@foreach($messages as $message)
<tr align="{{ $message->id == $id ? 'left' : 'right' }}">
// 省略
@endforeach
## Vue.jsでの三項演算子
– attributeの前にコロン(:)をつける
– 条件判定はカッコ()で囲う
<div v-for="m in messages">
<tr :align="(m.id === {{ $id }}) ? 'left' : 'right'">
// 省略
</div>
できるんかいな。ワクワクします。