Laravel 5 集成了 Auth 功能,并且包含了一个注册登录功能,通过这个集成,可以轻松实现用户用户注册登录,下文作为一个简易 Demo 示例如何使用。
参考:Database Setup Laravel 5.1
How to Make User Login and Registration Laravel 5.1
Laravel 5.1 中文文档 - 系统服务 - 用户认证
数据库部分
我们假设现在没有搭建 Homestead 环境,在本机上已经安装了 MySQL | MariaDB 数据库(推荐 MySQL 5.6 及以上版本 或 MariaDB 10)。
新建数据库 laravel
或任意名称,假设数据库用户名以及密码均为 root
。进入 Laravel 项目目录,编辑 .env
文件:【仅编辑如下部分,DB_CONNECTION
无论是 MySQL 还是 MariaDB 值均为 mysql
】
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
将 DB_DATABASE
值修改为已创建的数据库名称,例如 laravel
,将 DB_USERNAME
和 DB_PASSWORD
值修改为正确的数据库用户名以及密码。如果没有此文件,请先复制一份 .env.example
文件并重命名为 .env
。
接下来我们要调用 Migration 功能,参考资料:Laravel 5.1 中文文档 - 数据库 - 数据库迁移,你可以在 database/migrations
目录里看到两个文件 2014_10_12_000000_create_users_table.php
和 2014_10_12_100000_create_password_resets_table.php
。我们在项目根目录,例如 /Users/mine/Sites/myproject
打开终端,执行
php artisan migrate
当然前提是你的 php
命令应当在这之前写进环境变量,运行成功后,终端会提示:
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
利用 mysql
命令或 Navicat 一类的软件可以查看到数据库里面多了 migrations
、password_resets
、users
三张表。migrations
表用于跟踪所有迁移,可以忽略。接下来继续下面的 Laravel 部分
Laravel 部分
创建路由
编辑 app/Http/routes.php
文件,创建注册以及登录用户的路由,有两种方式实现,下面为第一种。需要注意在路由 URL 后的控制器参数上跟上 Auth 这个路径,因为 AuthController
在 app/Http/Controllers/Auth
下。
// 登录认证路由
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@postLogin');
Route::get('auth/logout', 'Auth\AuthController@getLogout');
// 注册用户路由
Route::get('auth/register', 'Auth\AuthController@getRegister');
Route::post('auth/register', 'Auth\AuthController@postRegister');
// 重置密码路由(可忽略)
Route::controllers([
'password' => 'Auth\PasswordController',
]);
// 第二种方式通过路由群组实现
Route::group(['namespace' => 'Auth'], function () {
// 登录认证路由
Route::get('auth/login', 'AuthController@getLogin');
Route::post('auth/login', 'AuthController@postLogin');
Route::get('auth/logout', 'AuthController@getLogout');
// 注册用户路由
Route::get('auth/register', 'AuthController@getRegister');
Route::post('auth/register', 'AuthController@postRegister');
// 重置密码路由(可忽略)
Route::controllers(['password' => 'PasswordController',]);
});
从上面两个例子可以看出差异,通过路由群组,在 namespace
指定了 Auth
目录后,接下来的路由里就无需写上 Auth\
了,如果多个路由在同一子目录下,推荐使用路由群组实现。本例里 2 选 1 即可。
创建视图
看到上方的代码一定会非常好奇,为什么?因为在 AuthController
里根本没有任何关于 login
、register
、logout
的方法,唯一一个 getLogout
方法似乎和我们路由上绑定的又没什么关系。是不是文档写错了?当然没有,我们也无需去完善这样的方法,如果我告诉你只要把视图页面做好就能注册登录了,你会不会很惊讶?这就是接下来我们要做的,添加一个简单的视图。首先进入 resources/views
目录,新建文件夹 auth
,在 auth
里新建 register.blade.php
和 login.blade.php
文件。先别急着想为什么,后面会有解释。分别在 register.blade.php
和 login.blade.php
里写入以下内容:
<!-- resources/views/auth/register.blade.php -->
<form method="POST" action="/auth/register">
{!! csrf_field() !!}
<div>
名称
<input type="text" name="name" value="{{ old('name') }}">
</div>
<div>
Email
<input type="email" name="email" value="{{ old('email') }}">
</div>
<div>
密码
<input type="password" name="password">
</div>
<div>
确认密码
<input type="password" name="password_confirmation">
</div>
<div>
<button type="submit">注册</button>
</div>
</form>
<!-- resources/views/auth/login.blade.php -->
<form method="POST" action="/auth/login">
{!! csrf_field() !!}
<div>
Email
<input type="email" name="email" value="{{ old('email') }}">
</div>
<div>
密码
<input type="password" name="password" id="password">
</div>
<div>
<input type="checkbox" name="remember"> 记住我
</div>
<div>
<button type="submit">登录</button>
</div>
</form>
完成上述操作后,我们在浏览器访问一下,当然很重要的一点是你服务器中【例如 Nginx 和 Apache】root
对应的目录为 laravelproject/public
而不是 laravelproject
目录。我们访问 http://HOST:PORT/auth/register
和 http://HOST:PORT/auth/login
可以看到页面能够正常访问。我们在登录页面尝试一下在 Email
和 密码
分别输入 123
然后登录:
这非常有趣,我们并没有做前端的任何验证和 UI,而且表单也没有跳转,直接就在前端验证了 123
不是 Email 并且展现提示。这里不做多的解释,如果对此项感兴趣或有需求,可以参阅慕课网:轻松学会Laravel-表单篇 以及 Laravel 5.1 中文文档 - 系统服务 - 表单验证
注册登录
我们可以尝试一下注册用户以及登录,当然注册后会遇到一个 404,你会发现注册成功后进入了 http://HOST:PORT/home
,因为我们并没有定义这个路由。解决方法非常简单,编辑 app/Http/Controllers/Auth/AuthController
在 Class 里面找到:
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
在其下方添加一行:
// 注册成功后重定向
protected $redirectPath = '/';
// 使用 $redirectTo 实现相同功能
现在再次注册,注册成功后会跳转到 Laravel 首页,但是打不开注册和登录页面是怎么回事?这是因为 Cookie
的原因,默认注册成功后会自动登录。我们可以通过访问 auth/logout
注销登录解决;也可以在 Chrome 开发者工具点击 Application 标签,展开 Cookie
,右键 Clear
掉就能再次出现注册登录界面了。
如果一路顺畅,此时数据库的 users
表已经存在了刚刚注册的用户数据。
浅入一下
回到 app/Http/Controllers/Auth/AuthController.php
,找到:
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
这是一个什么东西?它叫做 Trait,意思是 特点、特征,Trait 是一个类,可以被其他类使用,这货和继承类似,只需要用 use
加载 trait
,trait
内的所有方法都可以被使用,详情戳这里:PHP: Trait - 手册。我们按住 Ctrl 鼠标左键点击 AuthenticatesAndRegistersUsers
跟踪一下,得到:【此文件存在于 vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesAndRegistersUsers.php
】
<?php
namespace Illuminate\Foundation\Auth;
trait AuthenticatesAndRegistersUsers
{
use AuthenticatesUsers, RegistersUsers {
AuthenticatesUsers::redirectPath insteadof RegistersUsers;
}
}
不难发现,这里面也用了两个 Trait,AuthenticatesUsers
和 RegistersUsers
。我们先看看 RegistersUsers
,同样 Ctrl 跟踪,终于看到久违的 getRegister
和 postRegister
:
/**
* Show the application registration form.
*
* @return \Illuminate\Http\Response
*/
public function getRegister()
{
return view('auth.register');
}
/**
* Handle a registration request for the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function postRegister(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
Auth::login($this->create($request->all()));
return redirect($this->redirectPath());
}
发现了什么?在 getRegister
中,返回的视图叫做 auth.register
,在 Laravel 中,auth.register
等同于 auth/register
。还记得 resources/views/auth
里面的 register.blade.php
吗?就是返回的它。如果此文件是放在其他目录,当然是不能加载的,这就是为什么我们在 views
目录里再新建了一个子目录 auth
的原因。
再看看 postRegister
,返回了 redirectPath
,Ctrl 一下,真相大白:
public function redirectPath()
{
if (property_exists($this, 'redirectPath')) {
return $this->redirectPath;
}
return property_exists($this, 'redirectTo') ? $this->redirectTo : '/home';
}
如果属性 redirectPath
存在即返回;如果不存在,判断是否存在 redirectTo
,如果也不存在,返回默认 /home
,这就是为什么在没有 redirectPath
属性时会 404 的原因。
登录的实现在 AuthenticatesUsers.php
,里面包含了 getLogin
、postLogin
、getLogout
等方法。最下方有一个“油门登录”方法【Throttle 这货就是油门 lol】,Ctrl 一下 ThrottlesLogins
,里面实现多次登录尝试等方法,找到:
protected function maxLoginAttempts()
{
return property_exists($this, 'maxLoginAttempts') ? $this->maxLoginAttempts : 5;
}
又是熟悉的代码,maxLoginAttempts
属性如果不存在,默认为 5
。那么我们可以在 AuthController
里同样的添加上这个属性来改变最大尝试登录次数。例如:
protected $maxLoginAttempts = 10;
当然不要忘记把它写在 use
两个 Trait 的下方。