ここまでの作業では,架空のメールアドレスでも登録ができてしまう.ここでは,ユーザが登録したときにメールが届き,受信したユーザがリンクをクリックして初めて登録が完了するようにしたい.
データベースのマイグレーションファイルを変更して,2つの列を追加する.
database/migrations/2014_10_12_000000_create_users_table.php
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->integer('student_id')->unique();
$table->string('login_id')->unique();
$table->string('password');
$table->rememberToken();
$table->string('email_token')->nullable();
$table->tinyInteger('verified')->default(0);
$table->timestamps();
});
}
ジョブの待ち行列に関するテーブルも作成する.
[GakuinHana@rin06 laravelUser]$ php artisan queue:table ⏎ Migration created successfully! [GakuinHana@rin06 laravelUser]$ php artisan queue:failed-table ⏎ Migration created successfully! [GakuinHana@rin06 laravelUser]$
ユーザが登録変更をできるように,モデルの $fillable
に追加する.
app/User.php (抜粋)
protected $fillable = [
'name', 'email', 'password',
'student_id', 'login_id',
'email_token', 'verified',
];
artisan コマンドでメール認証クラスを作成する.
[GakuinHana@rin06 laravelUser]$ php artisan make:mail EmailVerification ⏎ Mail created successfully. [GakuinHana@rin06 laravelUser]$
上のコマンドを実行すると,app/Mail ディレクトリが作成され,その中に EmailVerification.php の雛形が作成された.
app/Mail/EmailVerification.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class EmailVerification extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('view.name');
}
}
上の EmailVerification.php を編集して,ユーザモデルを追加する.
app/Mail/EmailVerification.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;
class EmailVerification extends Mailable
{
use Queueable, SerializesModels;
public $user;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('email.email')
->with([
'email_token' => $this->user->email_token
]);
}
}
resources/views/ に email というフォルダを作成し email.blade.php を作る.
resources/views/email/email.blade.php
<h1>Click the Link To Verify Your Email</h1>
<p>あなたのメールアドレスを検証するために次のリンクをクリックしてください.<br>
{{url('/auth/verifyemail/'.$email_token)}} </p>
<p>心当たりが無い場合は無視してください.</p>
artisan コマンドで新たな queue job 作成する.なお,キューの詳細はこちらで確認できる.
[GakuinHana@rin06 laravelUser]$ php artisan make:job SendVerificationEmail ⏎ Job created successfully. [GakuinHana@rin06 laravelUser]$
上のコマンドで app/ ディレクトリ内に Jobs ディレクトリが作成され,この中に SendVerificationEmail.php ファイルが生成された.
app/Jobs/SendVerificationEmail.php
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class SendVerificationEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
}
}
このファイルを次のように編集する.
app/Jobs/SendVerificationEmail.php
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Mail;
use App\Mail\EmailVerification;
class SendVerificationEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$email = new EmailVerification($this->user);
Mail::to($this->user->email)->send($email);
}
}
コントローラを次のように編集する.
app/Http/Controllers/Auth/RegisterController.php
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use App\Jobs\SendVerificationEmail;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'student_id' => 'required|integer|min:6100000|max:6199999|unique:users',
'login_id' => 'required|string|min:1|max:255|unique:users',
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'student_id' => $data['student_id'],
'login_id' => $data['login_id'],
'email_token' => base64_encode($data['email']),
]);
}
/**
* Handle a registration request for the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
dispatch(new SendVerificationEmail($user));
return view('auth.verification');
}
/**
* Handle a registration request for the application.
*
* @param $token
* @return \Illuminate\Http\Response
*/
public function verify($token)
{
$user = User::where('email_token',$token)->first();
$user->verified = 1;
if($user->save()) {
return view('auth.emailconfirm',['user'=>$user]);
}
}
}
ユーザ登録後に「メールをお送りしました」という画面を表示したいので,そのページのビューを作る.
resources/views/auth/verification.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<h1>ユーザ登録</h1>
<p>ユーザ登録を行いました.</p>
<p>確認のためにEメールを送信しましたので,メールのリンクをクリックしてください.</a></p>
</div>
</div>
</div>
</div>
@endsection
さらに,メールのリンクをクリックして検証が終わったあとに表示されるページのビューを作る.
resources/views/auth/emailconfirm.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<h1>メールアドレスが確認できました</h1>
<p>あなたのメールアドレスが確認できました.</p>
<p><a href="{{url('/login')}}">ここからログインしてください.</a></p>
</div>
</div>
</div>
</div>
@endsection
メールのリンクをクリックしたときに渡される /auth/verifyemail へのルートを定義する.
routes/web.php (抜粋)
Route::get('/', function () {
return view('welcome');
});
Route::get('/auth/verifyemail/{token}', 'Auth\RegisterController@verify');
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
ステップの最初にマイグレーションファイルを編集して,テーブルのスキーマを変更したので,データベースをリセットしておく.
[GakuinHana@rin06 laravelUser]$ php artisan migrate:rollback; php artisan migrate; php artisan db:seed ⏎
メールによる検証ができるようになったので,実際に実験してみよう.まずは,データベースのリセットをしておく.
[GakuinHana@rin06 laravelUser]$ php artisan migrate:rollback; php artisan migrate; php artisan db:seed ⏎
トップページから REGISTER へのリンクをクリックする.E-Mail Address には正しい(自分で受信可能な)メールアドレスを入力する.その他は適当な値でよい.
上で Register ボタンを押すと,次のような画面になる.
メールを確認して,リンクをクリックする.
メールのリンクをクリックすると,次の画面になり,認証された.
実際にログインIDでログインしてみる.
うまくログインできました.一見うまく行ったようです.
これまでの作業で,一見するとうまくメールでの認証ができたように思われます.しかしながら,まだ問題点がいくつか残っているので,その問題点を確認してみよう.
一旦,データベースをリセットしてから,Webから登録作業を行います.その途中で sqlite でデータベースの内容を確認します.
[GakuinHana@rin06 laravelUser]$ php artisan migrate:rollback; php artisan migrate; php artisan db:seed ⏎ Rolling back: 2018_07_01_163336_create_failed_jobs_table ... (中略) ... Seeding: UsersTableSeeder [GakuinHana@rin06 laravelUser]$ sqlite3 database/database.sqlite ⏎ SQLite version 3.6.20 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> select * from users; ⏎ ## ユーザ登録前 1|A. Sample|a@sample.com|6101701|user_a|$2y$10$oJVKp5XFGUD8i5XfhECqIeGyJphruzEL/2fT5qdWwULpEgrCvA.Y.|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 2|B. Sample|b@sample.com|6101702|user_b|$2y$10$.OnT/mPj9wtgBPf51AAQJOJZK7N6vxcp67oYNUyalOjwOpnVKVSy6|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 3|C. Sample|c@sample.com|6101703|user_c|$2y$10$mqSsPThslJJaMZxjZs9CuurLJmjH6UV826g5tYfcuVfpLnfWJLrhS|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 sqlite> select * from users; ⏎ ## ユーザ登録後(メール送信後) 1|A. Sample|a@sample.com|6101701|user_a|$2y$10$oJVKp5XFGUD8i5XfhECqIeGyJphruzEL/2fT5qdWwULpEgrCvA.Y.|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 2|B. Sample|b@sample.com|6101702|user_b|$2y$10$.OnT/mPj9wtgBPf51AAQJOJZK7N6vxcp67oYNUyalOjwOpnVKVSy6|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 3|C. Sample|c@sample.com|6101703|user_c|$2y$10$mqSsPThslJJaMZxjZs9CuurLJmjH6UV826g5tYfcuVfpLnfWJLrhS|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 4|Koichiro Rinsaka|rinsaka@sample.com|6120001|rinsaka|$2y$10$RghjYqdp545rdc4fmlSKxu1YHrTsGKkRMdSipGVykJx6J/aE1Myny||a29pY2hpcm8ucmluc2FrYUBnbWFpbC5jb20=|0|2018-07-01 17:49:10|2018-07-01 17:49:10 sqlite> select * from users; ⏎ ## メールのリンクをクリックしたあと 1|A. Sample|a@sample.com|6101701|user_a|$2y$10$oJVKp5XFGUD8i5XfhECqIeGyJphruzEL/2fT5qdWwULpEgrCvA.Y.|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 2|B. Sample|b@sample.com|6101702|user_b|$2y$10$.OnT/mPj9wtgBPf51AAQJOJZK7N6vxcp67oYNUyalOjwOpnVKVSy6|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 3|C. Sample|c@sample.com|6101703|user_c|$2y$10$mqSsPThslJJaMZxjZs9CuurLJmjH6UV826g5tYfcuVfpLnfWJLrhS|||0|2018-07-01 17:47:26|2018-07-01 17:47:26 4|Koichiro Rinsaka|rinsaka@sample.com|6120001|rinsaka|$2y$10$RghjYqdp545rdc4fmlSKxu1YHrTsGKkRMdSipGVykJx6J/aE1Myny|GeFRoIaNJFJDahRUGgp7wrULEYmui23Nn0Tmqzqyz7k3gudPLSOe8FfmAYBn|a29pY2hpcm8ucmluc2FrYUBnbWFpbC5jb20=|1|2018-07-01 17:49:10|2018-07-01 17:50:10 sqlite> .exit ⏎ [GakuinHana@rin06 laravelUser]$
上の結果のとおり,メールのリンクをクリックして初めてテーブルの9列目 verified 属性の値が 1 になる.本来なら verified の値が 1 になるまで(つまり,メールアドレスの確認が終わるまで),ログインできないようにすべきでしょう.
まず,データベースをリセットして,実験してみよう.実際に,ユーザ登録をした直後にログインができており,メールのリンクをクリックする前に,ログアウト,再度ログインの作業をしてみよう.やはりログインできてしまうのは問題でしょう.
ここで,メールアドレスの確認をするまで(つまりverified の値が1になるまで),ログインできないようにしよう.
app/Http/Controllers/Auth/LoginController.php を編集する.ログインが成功した直後に authenticated()
関数が呼ばれるが,これは vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php に定義されている.この authenticated()
をオーバーライドするために,app/Http/Controllers/Auth/LoginController.php に記述する.(vendor/ 以下にある AuthenticatesUsers.php を直接編集するわけではないことに注意しよう.)
app/Http/Controllers/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
/**
* The user has been authenticated.
*
* @param \Illuminate\Http\Request $request
* @param mixed $user
* @return mixed
*/
protected function authenticated(Request $request, $user)
{
// ログイン後にここが呼び出される
// メールでの認証が済んでいるかをチェックする
if(!$user->verified) {
// メールでの認証が済んでいないので強制ログアウト
$this->guard()->logout();
$request->session()->invalidate();
return redirect('/login')->with('warning', 'メールの確認をしてください');
}
}
public function username()
{
return 'login_id';
}
}
トップページ (welcome.blade.php) にフラッシュメッセージを表示するようにする.
resources/views/welcome.blade.php (抜粋)
<body>
{{-- フラッシュメッセージの表示 --}}
@if (session('warning'))
<div class="alert alert-warning">
{{ session('warning') }}
</div>
@endif
@if (session('status'))
<div class="alert alert-info">
{{ session('status') }}
</div>
@endif
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@if (Auth::check())
<a href="{{ url('/home') }}">Home</a>
@else
<a href="{{ url('/login') }}">Login</a>
<a href="{{ url('/register') }}">Register</a>
@endif
</div>
@endif
<div class="content">
<div class="title m-b-md">
Laravel
</div>
<div class="links">
<a href="https://laravel.com/docs">Documentation</a>
<a href="https://laracasts.com">Laracasts</a>
<a href="https://laravel-news.com">News</a>
<a href="https://forge.laravel.com">Forge</a>
<a href="https://github.com/laravel/laravel">GitHub</a>
</div>
</div>
</div>
</body>
ログインページにもフラッシュメッセージを表示するようにする.
resources/views/auth/login.blade.php (抜粋)
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Login</div>
<div class="panel-body">
{{-- フラッシュメッセージの表示 --}}
@if (session('warning'))
<div class="alert alert-warning">
{{ session('warning') }}
</div>
@endif
@if (session('status'))
<div class="alert alert-info">
{{ session('status') }}
</div>
@endif
<form class="form-horizontal" method="POST" action="{{ route('login') }}">
{{ csrf_field() }}
テスト用のユーザでもログインできるように,シーダーを変更しておく.(たとえば,user_c だけ変更せずにどのような動作になるか検証するとよい.)
database/seeds/UsersTableSeeder.php
public function run()
{
DB::table('users')->delete();
User::create([
'name' => 'A. Sample',
'email' => 'a@sample.com',
'student_id' => 6101701,
'login_id' => 'user_a',
'password' => bcrypt('abc'),
'verified' => 1,
'created_at' => Carbon::now()
]);
User::create([
'name' => 'B. Sample',
'email' => 'b@sample.com',
'student_id' => 6101702,
'login_id' => 'user_b',
'password' => bcrypt('abc'),
'verified' => 1,
'created_at' => Carbon::now()
]);
User::create([
'name' => 'C. Sample',
'email' => 'c@sample.com',
'student_id' => 6101703,
'login_id' => 'user_c',
'password' => bcrypt('abc'),
'verified' => 0,
'created_at' => Carbon::now()
]);
}
実際にデータベースをリセットしてから,実験してみよう.新規ユーザ (rinsaka) や user_c でログインすると強制的にログアウトになり,フラッシュメッセージが表示されます.
強制的にログアウトされ,フラッシュメッセージが表示された.フラッシュメッセージのスタイルはこのあたりを参考に設定すれば良い.
このあとは確認メールの有効期限の設定と確認メールの再送信を実現しよう.
users テーブルに登録メールを送信した日時を記録するための属性を追加する.
database/migrations/2014_10_12_000000_create_users_table.php (抜粋)
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Carbon\Carbon;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->integer('student_id')->unique();
$table->string('login_id')->unique();
$table->string('password');
$table->rememberToken();
$table->string('email_token')->nullable();
$table->tinyInteger('verified')->default(0);
$table->timestamp('sent_at')->default(Carbon::now());
$table->timestamps();
});
}
データベースをリセットしておく.
[GakuinHana@rin06 laravelUser]$ php artisan migrate:rollback; php artisan migrate; php artisan db:seed ⏎ Rolling back: 2018_07_01_163336_create_failed_jobs_table Rolled back: 2018_07_01_163336_create_failed_jobs_table Rolling back: 2018_07_01_163318_create_jobs_table Rolled back: 2018_07_01_163318_create_jobs_table Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table Migrating: 2018_07_01_163318_create_jobs_table Migrated: 2018_07_01_163318_create_jobs_table Migrating: 2018_07_01_163336_create_failed_jobs_table Migrated: 2018_07_01_163336_create_failed_jobs_table Seeding: UsersTableSeeder [GakuinHana@rin06 laravelUser]$
app/Http/Controllers/Auth/RegisterController.php の verify() 関数を修正し,確認メールのリンクがリクエストされたときに経過時間を検証するようにする.
app/Http/Controllers/Auth/RegisterController.php (抜粋)
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use App\Jobs\SendVerificationEmail;
use Carbon\Carbon;
class RegisterController extends Controller
{
... (中略) ...
public function verify($token)
{
$user = User::where('email_token',$token)->first();
// 現在の時刻を取得
$date_now = new Carbon(Carbon::now());
// メールの送信時刻を取得し,1時間加えた時刻を有効期限とする
$date_expire = Carbon::createFromFormat('Y-m-d H:i:s', $user->sent_at);
$date_expire->addHour();
// リンクの有効期限のチェック
if ($date_now->gt($date_expire)) { // gt は Grater Than,つまり "より大きい"
return redirect('/')
->with('warning', 'メールリンクの有効期限(1時間)を過ぎました');
}
$user->verified = 1;
if($user->save()) {
return view('auth.emailconfirm',['user'=>$user]);
}
}
}
メールの送信から1時間以上経過した段階でメールのリンクをクリックすると次のような画面になる(1時間待つのが面倒であれば,上の26行目をコメントアウトすると良い).また1時間以内の場合にはメールアドレスの検証ができることも確認しておこう.
メールリンクの有効期限が設定できたので,期限が切れた場合やメールが届かなかった場合に認証メールを再送信できるようにする.
routes/web.php にルートを記述する.この中の Auth::routes();
という記述によって認証に必要なルートがまとめて定義される.この定義を artisan コマンドで確認する.
[GakuinHana@rin06 laravelUser]$ php artisan route:list ⏎ +--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | auth/verifyemail/{token} | | App\Http\Controllers\Auth\RegisterController@verify | web,guest | | | GET|HEAD | home | home | App\Http\Controllers\HomeController@index | web,auth | | | POST | login | | App\Http\Controllers\Auth\LoginController@login | web,guest | | | GET|HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest | | | POST | logout | logout | App\Http\Controllers\Auth\LoginController@logout | web | | | POST | password/email | password.email | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web,guest | | | GET|HEAD | password/reset | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest | | | POST | password/reset | | App\Http\Controllers\Auth\ResetPasswordController@reset | web,guest | | | GET|HEAD | password/reset/{token} | password.reset | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web,guest | | | GET|HEAD | register | register | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest | | | POST | register | | App\Http\Controllers\Auth\RegisterController@register | web,guest | | | GET|HEAD | users/{id} | | App\Http\Controllers\UsersController@show | web,auth | +--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------+ [GakuinHana@rin06 laravelUser]$
上の定義を参考に routes/web.php に定義を追加する.
routes/web.php (抜粋)
Route::get('/', function () {
return view('welcome');
});
Route::get('/auth/verifyemail/{token}', 'Auth\RegisterController@verify');
Auth::routes();
Route::get('/resend', 'Auth\RegisterController@showReSendForm')->name('resend');
Route::post('/resend', 'Auth\RegisterController@reSend');
Route::get('/home', 'HomeController@index')->name('home');
Route::get('/users/{id}', 'UsersController@show');
定義ができたらルートを再度確認する.
[GakuinHana@rin06 laravelUser]$ php artisan route:list ⏎
+--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/user | | Closure | api,auth:api |
| | GET|HEAD | auth/verifyemail/{token} | | App\Http\Controllers\Auth\RegisterController@verify | web,guest |
| | GET|HEAD | home | home | App\Http\Controllers\HomeController@index | web,auth |
| | POST | login | | App\Http\Controllers\Auth\LoginController@login | web,guest |
| | GET|HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest |
| | POST | logout | logout | App\Http\Controllers\Auth\LoginController@logout | web |
| | POST | password/email | password.email | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web,guest |
| | GET|HEAD | password/reset | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest |
| | POST | password/reset | | App\Http\Controllers\Auth\ResetPasswordController@reset | web,guest |
| | GET|HEAD | password/reset/{token} | password.reset | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web,guest |
| | POST | register | | App\Http\Controllers\Auth\RegisterController@register | web,guest |
| | GET|HEAD | register | register | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest |
| | POST | resend | | App\Http\Controllers\Auth\RegisterController@reSend | web,guest |
| | GET|HEAD | resend | resend | App\Http\Controllers\Auth\RegisterController@showReSendForm | web,guest |
| | GET|HEAD | users/{id} | | App\Http\Controllers\UsersController@show | web,auth |
+--------+----------+--------------------------+------------------+------------------------------------------------------------------------+--------------+
[GakuinHana@rin06 laravelUser]$
Register ページにメール再送信ページへのリンクを設置する.
resources/views/auth/register.blade.php (抜粋)
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Register
</button>
</div>
</div>
</form>
<p><a href="{{ route('resend') }}">Send register link again</a></p>
</div>
</div>
</div>
</div>
</div>
@endsection
コントローラに2つの関数を追加する.
app/Http/Controllers/Auth/RegisterController.php (抜粋)
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
dispatch(new SendVerificationEmail($user));
return view('auth.verification');
}
public function showReSendForm()
{
dd("showReSendForm");
}
public function reSend(Request $request)
{
dd($request);
}
Webサーバを再起動して,/register からリンクを表示してみる.
コントローラからビューを呼び出す.
app/Http/Controllers/Auth/RegisterController.php (抜粋)
public function showReSendForm()
{
return view('auth.resend');
}
ビューを作る.なお,register.blade.php をコピーして編集する(メールアドレスの入力ボックスだけ残し,呼び出し先の変更をする)と良い.
resources/views/auth/resend.blade.php (抜粋)
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Send register mail link again</div>
<div class="panel-body">
{{-- フラッシュメッセージの表示 --}}
@if (session('warning'))
<div class="alert alert-warning">
{{ session('warning') }}
</div>
@endif
@if (session('status'))
<div class="alert alert-info">
{{ session('status') }}
</div>
@endif
<form class="form-horizontal" method="POST" action="{{ route('resend') }}">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required>
@if ($errors->has('email'))
<span class="help-block">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Send Again
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
再送信のリンクをクリックして,適当なメールアドレスを入力する.最後に「Send Again」ボタンをクリックする.
メールアドレスを取得できていることが確認できる.
メールの再送信処理を記述しよう.ただし,まだ登録されていないアドレスやすでに検証が済んでいるアドレスに送信しても意味がないので,そのようなチェックは予め行っておく.
app/Http/Controllers/Auth/RegisterController.php (抜粋)
public function reSend(Request $request)
{
$user = User::where('email', $request->email)->first();
if (!$user) {
return redirect('/resend')
->with('warning', '登録されていないアドレスです');
}
if ($user->verified == 1) {
return redirect('/resend')
->with('warning', 'すでに検証されています.ログイン画面からログインしてください');
}
// メールの送信時間を現在時刻に変更
$user->sent_at = Carbon::now();
$user->save();
// メールの送信ジョブを作成し,キューに投入する
event(new Registered($user));
dispatch(new SendVerificationEmail($user));
return view('auth.verification');
}
記述できたら,実際にメールの再送信を行い,リンクのクリックで検証できるかどうかを確かめよう.