Laravel の認証は php artisan make:auth
である程度のログイン機能が吐き出されて、あとはビューをちょちょいと変更したり Route 周りを自分の好みにカスタマイズしたりで非常に強力な認証が最小限の工数で利用できます。
しかしながら融通が効きにくいこともあり、例えばメールアドレス、パスワード以外の有効無効フラグを追加したいのだが、というときに公式ではこう記載されています。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
/**
* 認証を処理する
*
* @param \Illuminate\Http\Request $request
*
* @return Response
*/
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
// 認証に成功した
return redirect()->intended('dashboard');
}
}
}
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// ユーザーは存在しており、かつアクティブで、資格停止されていない
}
しかし、App\Http\Auth\LoginContoller.php
の実態たる Illuminate\Foundation\Auth\AuthenticatesUsers
ではこんな記述はでてきません。
そこでLaravel5.4のmake:auth再利用でハマったを参考にしてどうすればフラグを認証判定に含めることができるかを調べてみました。
例のごとく結論を知りたい方は末尾へどうぞ。
ここでは有効・無効のフラグを active
ではなく is_valid
としています。
調査
参考元のサイトを踏まえて追って行くと、
Illuminate\Auth\SessionGuard.php の attempt メソッドにたどり着きます。
public function attempt(array $credentials = [], $remember = false)
{
$this->fireAttemptEvent($credentials, $remember);
$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
if ($this->hasValidCredentials($user, $credentials)) {
$this->login($user, $remember);
return true;
}
$this->fireFailedEvent($user, $credentials);
return false;
}
retrieveByCredentials($credentials)
と hasValidCredentials($user, $credentials)
の実体が Illuminate\Auth\EloquentUserProvider.php
とのことなので確認。
public function retrieveByCredentials(array $credentials)
{
if (empty($credentials) ||
(count($credentials) === 1 &&
array_key_exists('password', $credentials))) {
return;
}
$query = $this->createModel()->newQuery();
foreach ($credentials as $key => $value) {
if (! Str::contains($key, 'password')) {
$query->where($key, $value);
}
}
return $query->first();
}
public function validateCredentials(UserContract $user, array $credentials)
{
$plain = $credentials['password'];
return $this->hasher->check($plain, $user->getAuthPassword());
}
retrieveByCredentials を確認すると、where でちゃんとパラメータが渡せるようになっていますね。
となると、key value 型の配列を $credentials に入れてあげれば良い。
$credentials が設定されているところは LoginController.php の継承元 Illuminate\Foundation\Auth\AuthenticatesUsers
にあります。
/**
* Get the needed authorization credentials from the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
$request->only を var_dump してみると、
array (size=2)
'email' => string 'xxxxx@xxxxxx.xxxxx' (length=xx)
'password' => string 'ABCDEFGH' (length=8)
という、素直な配列です。
ではコレに追加してやるだけですね。
結論
use Illuminate\Http\Request;
protected function credentials(Request $request)
{
$temporary = $request->only($this->username(), 'password');
$temporary['is_valid'] = 1;
return $temporary;
}
というわけで、is_valid は boolean 型ですので、1 なり true なりを渡してやるようにすれば、$credentials に追加することができ、DBの検索時 where に追加されるようになりました。