前へ | 次へ
環境の構築が完了したので、実際に機能を置き換えていきます。まずはユーザー登録を対応させます。
(2016/11/8 エラーを変数でviewに渡していたのを、withErrorに変更)
(2016/12/21 HTMLのidをケバブケースに修正)
(2016/12/21 テストにwantToを追加)
方針
Sentinelのユーザー登録についての公式ドキュメントはこちら。
ここでは次のことをします。
- ユーザー名と、メールアドレスと、パスワードと、確認用のパスワードを受け付ける
- ユーザー登録を完了するには、メールによる確認作業を必要にする
- ユーザー名、メールアドレス、パスワードは必須
- パスワードと確認用パスワードは一致していなければならない
ユーザー登録のテストを作成
ユーザー登録処理をSentinelに組み替えるにあたり、事前にテストコードを作成しておきます。
ボタンを確実に押すために、フォームにIDを設定します。
- resources/views/auth/register.blade.php をエディターで開く
- 「<form」から始まる行を見つけて、以下のようにID属性を追加する(idをケバブケースに修正 2016/12/21)
<form id="register-user-form" class="form-horizontal" role="form" method="POST" action="{{ url('/register') }}">
続いて、テスト用のCestファイルを作成しいます。
- ターミナルから以下を実行して、ユーザー登録用のテストコードを生成
composer exec codecept g:cest functional RegisterUser
- tests/functional/RegisterUserCest.php が出来上がるので、エディターで開く
- tryToTestメソッドを以下のようにする(submitFormのidをケバブケースに修正 2016/12/21)
// tests
public function tryToTest(FunctionalTester $I)
{
// 空欄での登録試みが失敗するのを確認
$I->wantTo(' 空欄での登録試みが失敗するのを確認.');
$I->amOnPage('/register');
$I->submitForm('#register-user-form', [
]);
$I->seeInCurrentUrl('register');
$I->see('name', '.help-block');
$I->see('email', '.help-block');
$I->see('password', '.help-block');
// パスワードの不一致を確認
$I->wantTo(' パスワードの不一致を確認.');
$I->amOnPage('/register');
$I->submitForm('#register-user-form', [
'name' => 'テスト名前2',
'email' => 'test2@test.com',
'password' => 'testpass',
'password_confirmation' => 'not'
]);
$I->seeInCurrentUrl('register');
$I->see('password', '.help-block');
// 登録成功
$I->wantTo(' ユーザーの登録成功を確認.');
$I->amOnPage('/register');
$I->submitForm('#register-user-form', [
'name' => 'テスト名前',
'email' => 'test@test.com',
'password' => 'testpass',
'password_confirmation' => 'testpass'
]);
$I->seeInCurrentUrl('login');
$I->see(trans('sentinel.after_register'));
}
以下をテストするコードです。
- 空欄での登録試みが失敗するのを確認
- パスワードの不一致を確認
- 登録成功
npm test で実行すると、エラーが発生します。まだ、ユーザー登録処理を Sentinel に入れ替えてなく、アサーションするための文字列も用意していません。このテストコードを通すことを目指して作業を進めていきます。
メールのテスト環境を構築
メール送信のテスト時に、実際に本当のメールアドレスに送信すると削除するなどが面倒です。そこで、テスト用のメールサービス Mailtrap.io — Fake smtp testing server. Dummy smtp email testing を利用することにします。
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=25
MAIL_USERNAME=<MailtrapのUsername>
MAIL_PASSWORD=<MailtrapのPassword>
MAIL_ENCRYPTION=null
以上で設定完了です。テストを実行した時のメールは、実際のメールアドレスではなく、 Mailtrap.io に届きますので、そちらで確認します。送信先に架空のメールアドレスが使えるのも便利です。
ユーザー登録コントローラーの作成
ユーザーを登録処理するコントローラーを作成します。アクティベーションが必要となるので、Laravel が事前に提供している処理は利用できません。独自のものに差し替えます。
- app/Http/Controllers/Auth/RegisterController.php をエディターで開いて、既存のコードを削除して、以下のものに差し替える
<?php
namespace App\Http\Controllers\Auth;
use Activation;
use Mail;
use Sentinel;
use App\User;
use App\Http\Controllers\Controller;
use App\Notifications\RegisterNotify;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
class RegisterController extends Controller
{
@var
protected $redirectTo = 'login';
@return
public function __construct()
{
$this->middleware('guest');
}
protected function register(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|between:6,255|confirmed',
]);
$credentials = [
'name' => $request['name'],
'email' => $request['email'],
'password' => $request['password'],
];
$user = Sentinel::register($credentials);
$activation = Activation::create($user);
$usermodel = User::where('email', $user->email)->get()[0];
$usermodel->notify(new RegisterNotify($activation->code));
return redirect($this->redirectTo)->with('info', trans('sentinel.after_register'));
}
}
コード内にある通知のための RegisterNotify クラスと、テスト用のメッセージがまだありません。テストコードを通すために、これらを用意します。
メッセージを作成
メッセージをハードコーディングするのを避けるために、言語ファイルを作成しておきます。
- resources/langフォルダー内の en フォルダーを複製して、複製したフォルダー名を ja に変更
- jaフォルダー内に sentinel.php というファイルを作成
- sentinel.php をエディターで開いて、以下のコードを追加
<?php
return [
'activate_title' => 'ユーザー登録を完了してください',
'after_register' => 'ご登録いただいたメールアドレスに、登録を完了するためのリンクを書いたメールを送信しました。メールを開いて、リンクを押して、ユーザー登録を完了させたら、以下からログインしてください。',
'register_user_title' => 'ユーザー登録',
'register_user_name' => '様',
'register_user_intro' => 'へのユーザー登録を完了するには、以下のボタン(あるいはリンク)をクリックしてください。',
'register_user_button' => 'ユーザーを有効にする',
'register_user_outro' => '----',
'notify_footer_message' => '*このメールは送信専用アドレスから送信しています。返信はできません。',
'notify_footer_caution' => 'ボタンを押してもうまく動作しない場合は、以下のURLをコピーして、Webブラウザーのアドレス欄にペーストしてみてください。',
'system_mail' => 'システムメール',
];
- 英文が必要な場合は、上記と同じキーに、英語を代入したものを en フォルダーの sentinel.php に追加する
- config/app.php をエディターで開く
- 'locale'と'fallback_locale'の2つの値を、'en' から 'ja' に変更する
以上で完了です。以降、sentinel.phpに追加した配列を、PHPのコードからは trans('sentinel.要素名')、bladeからは@lang('sentinel.要素名')で参照できます。
通知のスタブ作成
ユーザーをアクティベーションするためのメッセージを送信させる通知を作成します。この段階では、テストを通すことを優先して中身のないスタブクラスとします。
- ターミナルで、以下を実行して、ユーザー登録、登録完了、リマインダー、リマインダー完了の通知を作成
php artisan make:notification RegisterNotify
このままで、とりあえず指定のユーザーにメールを送信します。中身は後で実装します。
ルートの設定
コントローラーができたので、registerで呼び出したら登録するようにルートを設定します。テスト時に出てくるので、 login のルートも設定しておきます。
- routes/web.php をエディターで開く
- Auth::routes(); は、Laravelのauthは利用しないので削除
- POSTメソッドのregisterで登録を発動させるので、Auth::routes() があった場所に、以下を追加(ログイン用のルートを修正 2016/11/8)
// ログイン用のルート
Route::get('login', function() {return view('auth.login', [
'info' => session('info')
])->withErrors(session('myerror'));})->name('login');
Route::post('login', 'Auth\LoginController@login');
// ユーザー登録用のルート
Route::get('register', function() {return view('auth.register');});
Route::post('register', 'Auth\RegisterController@register');
登録後のメッセージを表示できるように、loginビューに表示領域を追加します。
- resources/views/auth/login.blade.php をエディターで開く
- <div class="panel-body"> という行の下に、以下を追加(エラーの部分を修正 2016/11/8)
@if(isset($info))
<div class="alert alert-info">
{{ $info }}
</div>
@endif
@include('parts.errors')
エラーのビューをJavaScriptやその他の文言に対応できるように修正します(2016/11/8追加)。
- resources/views/parts/errors.blade.php を作成して、エディターで開く
- 以下のコードを入力する
<div id="error-block" class="alert alert-danger" @if (count($errors) == 0) style="display: none;" @endif >
<strong>以下のエラーが発生しました。</strong>
<br>
<ul id="error-list">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
以上で、 view から info と myerror を受け取った場合、ログイン画面にメッセージを表示します。
Registerビューの調整
必要な項目は揃っているので変更しなくても構いません。表記を変更したり、表示を日本語にしたい、独自の欄を設けたい場合などの手順です。
- resources/views/auth/register.blade.php をエディターで開く
- 変更したい箇所を修正する
- 上書き保存
テスト
以上で最低限の機能が揃いました。 npm test をターミナルで実行してください。「OK (2 tests, 9 assertions)」と表示されて成功します。
また、 http://mailtrap.io に用意した Inbox の中身を確認してください。通知にあらかじめ用意されているメッセージが届きます。
通知時に送るメールのフォームを完成させます。すでに php artisan vendor:publish を実行しているので、必要なメールファイルが resources フォルダー内にありますので、それを編集します。
- resources/views/vendor/notifications/email.blade.php をエディターで開いて、以下に書き換える
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css" rel="stylesheet" media="all">
only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
</head>
<?php
$style = [
/* Layout ------------------------------ */
'body' => 'margin: 0; padding: 0; width: 100%; background-color: #F2F4F6;',
'email-wrapper' => 'width: 100%; margin: 0; padding: 0; background-color: #F2F4F6;',
/* Masthead ----------------------- */
'email-masthead' => 'padding: 25px 0; text-align: center;',
'email-masthead_name' => 'font-size: 16px; font-weight: bold; color: #2F3133; text-decoration: none; text-shadow: 0 1px 0 white;',
'email-body' => 'width: 100%; margin: 0; padding: 0; border-top: 1px solid #EDEFF2; border-bottom: 1px solid #EDEFF2; background-color: #FFF;',
'email-body_inner' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0;',
'email-body_cell' => 'padding: 35px;',
'email-footer' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0; text-align: center;',
'email-footer_cell' => 'color: #AEAEAE; padding: 35px; text-align: center;',
/* Body ------------------------------ */
'body_action' => 'width: 100%; margin: 30px auto; padding: 0; text-align: center;',
'body_sub' => 'margin-top: 25px; padding-top: 25px; border-top: 1px solid #EDEFF2;',
/* Type ------------------------------ */
'anchor' => 'color: #3869D4;',
'header-1' => 'margin-top: 0; color: #2F3133; font-size: 19px; font-weight: bold; text-align: left;',
'paragraph' => 'margin-top: 0; color: #74787E; font-size: 16px; line-height: 1.5em;',
'paragraph-sub' => 'margin-top: 0; color: #74787E; font-size: 12px; line-height: 1.5em;',
'paragraph-center' => 'text-align: center;',
/* Buttons ------------------------------ */
'button' => 'display: block; display: inline-block; width: 200px; min-height: 20px; padding: 10px;
background-color: #3869D4; border-radius: 3px; color: #ffffff; font-size: 15px; line-height: 25px;
text-align: center; text-decoration: none; -webkit-text-size-adjust: none;',
'button--green' => 'background-color: #22BC66;',
'button--red' => 'background-color: #dc4d2f;',
'button--blue' => 'background-color: #3869D4;',
];
?>
<?php $fontFamily = 'font-family: Arial, \'Helvetica Neue\', Helvetica, sans-serif;'; ?>
<body style="{{ $style['body'] }}">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $style['email-wrapper'] }}" align="center">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $style['email-masthead'] }}">
<a style="{{ $fontFamily }} {{ $style['email-masthead_name'] }}" href="{{ url('/') }}" target="_blank">
{{ config('app.name') }} {{trans('sentinel.register_user_title')}}
</a>
</td>
</tr>
<tr>
<td style="{{ $style['email-body'] }}" width="100%">
<table style="{{ $style['email-body_inner'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-body_cell'] }}">
<h1 style="{{ $style['header-1'] }}">
@if (! empty($greeting))
{{ $greeting }}
@else
@if ($level == 'error')
Error!
@else
Hello!
@endif
@endif
</h1>
@foreach ($introLines as $line)
<p style="{{ $style['paragraph'] }}">
{{ $line }}
</p>
@endforeach
@if (isset($actionText))
<table style="{{ $style['body_action'] }}" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<?php
switch ($level) {
case 'success':
$actionColor = 'button--green';
break;
case 'error':
$actionColor = 'button--red';
break;
default:
$actionColor = 'button--blue';
}
?>
<a href="{{ $actionUrl }}"
style="{{ $fontFamily }} {{ $style['button'] }} {{ $style[$actionColor] }}"
class="button"
target="_blank">
{{ $actionText }}
</a>
</td>
</tr>
</table>
@endif
@foreach ($outroLines as $line)
<p style="{{ $style['paragraph'] }}">
{{ $line }}
</p>
@endforeach
<p style="{{ $style['paragraph'] }}">
{{trans('sentinel.notify_footer_message') }}
</p>
@if (isset($actionText))
<table style="{{ $style['body_sub'] }}">
<tr>
<td style="{{ $fontFamily }}">
<p style="{{ $style['paragraph-sub'] }}">
"{{ $actionText }}"
{{trans('sentinel.notify_footer_caution')}}
</p>
<p style="{{ $style['paragraph-sub'] }}">
<a style="{{ $style['anchor'] }}" href="{{ $actionUrl }}" target="_blank">
{{ $actionUrl }}
</a>
</p>
</td>
</tr>
</table>
@endif
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table style="{{ $style['email-footer'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-footer_cell'] }}">
<p style="{{ $style['paragraph-sub'] }}">
© {{ date('Y') }}
<a style="{{ $style['anchor'] }}" href="{{ url('/') }}" target="_blank">{{ config('app.name') }}</a>.
All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
- resources/views/vendor/notifications/email-plain.blade.php をエディターで開いて、以下に書き換える
<?php
if (! empty($greeting)) {
echo $greeting, "\n\n";
} else {
echo $level == 'error' ? 'Error!' : 'Hello!', "\n\n";
}
if (! empty($introLines)) {
echo implode("\n", $introLines), "\n\n";
}
if (isset($actionText)) {
echo "{$actionText}", "\n", "{$actionUrl}", "\n\n";
}
if (! empty($outroLines)) {
echo implode("\n", $outroLines), "\n\n";
}
echo trans('sentinel.notify_footer_message'), "\n";
echo config('app.name'), trans('sentinel.system_mail'), "\n";
以上で、通知用のメール書式が設定できました。引き続き、通知を作成します。
通知(Notify)を作成
通知は、連絡先の情報を持ったモデルから notify メソッドを呼び出すことで、メッセージを送ることができる機能です。メール以外にも、データベースやSMS、Slackなどに通知ができます。通知を利用するには、該当するモデルに Notifiable トレイトを宣言します。
ユーザー登録通知を作成する
先に作成した RegisterNotify.php の中身を実装して、ユーザーに確認用のリンクを送信します。
- app/Notifications/RegisterNotify.php を開いて、以下のようにする
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class RegisterNotify extends Notification
{
use Queueable;
private $code;
@return
public function __construct($code)
{
$this->code = $code;
}
@param
@return
public function via($notifiable)
{
return ['mail'];
}
@param
@return
public function toMail($notifiable)
{
return (new MailMessage)
->subject(trans('sentinel.register_user_title'))
->greeting($notifiable->name.trans('sentinel.register_user_name'))
->line(config('app.name').trans('sentinel.register_user_intro'))
->action(trans('sentinel.register_user_button'),
url('activate', [base64_encode($notifiable->email), $this->code]))
->line(trans('sentinel.register_user_outro'));
}
}
以上で、通知が完成です。 npm test でテストを実行して、成功することを確認してください。その後、 https://mailtrap.io を確認するとアクティベーションのためのリンクをつけたメールが届きます。HTMLとTextの中身をそれぞれ確認してみてください。
以上で、ユーザーの登録は出来上がりです。次は、アクティベーションを実装します。
前へ | 次へ