[教程] Laravel 认证:同一个登录框内提供「用户名或邮箱」登录?
一个小技巧分享给大家。Laravel 默认的身份验证允许使用一个 email 字段登录。但也可同时使用 username 等类似的其他字段。Laravel 默认使用一个字段登录时只能用 email,但是我们也可以只使用 username来登录。
在本教程中,我们将看到如何只使用两个字段—— login 和 password 来登录。login 既可以是 email 也可以是 username。
让我们来创建允许你使用 email 或 uername 两者之一来登录的 Laravel 项目。
设置项目
首先使用laravel installer创建一个名为login的新laravel项目。我们将在本教程中使用laravel 5.6。
laravel new login
在 .env
文件中设置数据库配置.
运行以下命令以支持基本登录和注册。
php artisan make:auth
打开database/migrations
目录中的create_users_table.php
。 在up
中添加用户名字段以存储用户名。 为此,请复制下面的代码并替换up
方法。
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('username');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
现在,通过运行以下命令来迁移数据库。
php artisan migrate
注册用户
在数据库中添加用户名字段后,还需要更改Laravel默认注册页面以接受用户名并将其保存在数据库中。
注册页面
首先,让我们在用户注册表单中添加用户名输入的文本框。转到 resources/views/auth
目录中的 register.blade.php
。在名称行后添加以下代码以添加用户名输入字段的文本框。
<div class="form-group row">
<label for="username" class="col-md-4 col-form-label text-md-right">
{{ __('Username') }}
</label>
<div class="col-md-6">
<input id="username" type="text"
class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}"
name="username" value="{{ old('username') }}" required>
@if ($errors->has('username'))
<span class="invalid-feedback">
<strong>{{ $errors->first('username') }}</strong>
</span>
@endif
</div>
</div>
上面的代码非常简单。 我刚刚复制了Name输入框并使用username更改了属性。
注册控制器
前端设置完成之后只剩下后端后端逻辑。 打开 app/Http/Controllers/Auth
目录下的 RegisterController.php
文件。
在 validator
方法中,为username字段添加验证。下面这是编写过后的代码。
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'username' => 'required|string|max:255|unique:users',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
}
用户名是必须的,需要一个字符串,最多包含255个字符,并且在users表中的username字段中是唯一的。
在 create
方法中, 添加username字段,让username和其他字段一起保存到数据库中。下面是编写过后的 create
方法。
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'username' => $data['username'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
现在我们已经在注册流程中设置了username字段。
使用用户名或邮件登录
现在,在注册用户时添加了用户名。 让用户可以使用电子邮件或用户名登录。
登录页面
首先,我们需要对登录页面进行一些修改,尤其是在邮件地址的输入框。
打开 resources/views/auth
目录下的 login.blade.php
文件。现在替换表单中的邮件地址输入框的内容替换为下面的内容。
<div class="form-group row">
<label for="login" class="col-sm-4 col-form-label text-md-right">
{{ __('Username or Email') }}
</label>
<div class="col-md-6">
<input id="login" type="text"
class="form-control{{ $errors->has('username') || $errors->has('email') ? ' is-invalid' : '' }}"
name="login" value="{{ old('username') ?: old('email') }}" required autofocus>
@if ($errors->has('username') || $errors->has('email'))
<span class="invalid-feedback">
<strong>{{ $errors->first('username') ?: $errors->first('email') }}</strong>
</span>
@endif
</div>
</div>
别担心,我将解释上面的代码。基本上我们使用表单中的 login
发送用户输入的内容。Laravel会接收它,并且知道它是邮件还是用户名。它在请求中既可以代表邮件也可以代表用户名。所以,在 input
标签中的 value
属性中,如果 old('username')
或者 old('email')
其中的一个存在值就设置它。
检查错误时我们也是这样做的。 如果用户名或邮件位于errors数组中,我们会输出相应的错误。
登录控制器
让我们为登录设置后端逻辑. 打开 app/Http/Controllers/Auth
目录下的 LoginController.php
文件。下面是更新过后的登录控制器文件。
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
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';
/**
* Login username to be used by the controller.
*
* @var string
*/
protected $username;
/**
* Create a new controller instance.
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
$this->username = $this->findUsername();
}
/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function findUsername()
{
$login = request()->input('login');
$fieldType = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
request()->merge([$fieldType => $login]);
return $fieldType;
}
/**
* Get username property.
*
* @return string
*/
public function username()
{
return $this->username;
}
}
让我解释一下登录控制器中的每个更改。我们添加了一个新的用户名属性,我们将用它来存储登录字段是电子邮件或者用户名。 此字段只有两个值电子邮件或用户名。在构造函数中,我们调用 findUsername
方法。 在这个方法中,我们得到 login
输入的值。我们检查该字段是有效的电子邮件,如果是,我们将 $ fieldType
设置为 email
否则为 username
。然后我们使用 merge()
方法在请求中添加带有输入 login
的 $ fieldType
。merge()
方法基本上将新输入合并到当前请求的数组中。 然后我们返回$ fieldType
,它可以是email
或username
。
我们在类中添加的最后一个方法是username方法。 此方法覆盖了laravel用于获取要使用的登录用户名的 username
方法。
这就是在一个字段中使用电子邮件或用户名登录所需的全部内容。
在以下位置找到项目的完整源代码 GitHub.
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
这个能使用电子邮箱和用户名登录,如果加上电话号码呢?怎么区分 fieldType?
@Evan 那你就只能限制用户名的逻辑 不允许存数字账号 这样的话用正则判断出是不是纯数字就能区别开了
嗯,文章这个适合个人用。
一般都有手机了,手机登录很常见。所以登录时,直接以name=登录方式比较好用点。jQuery、Vue或 React 直接切换。
我加了正则判断手机号码
@Evan 17号段忘了
@Evan 你如果用户注册的地方不做限制 用户恶意注册手机号段的账号 你就麻烦了
@lovecn
另外 推荐个正则表达式
如果用户的名字叫做某个别人的手机号可咋整。。。