如果你的网站有积分功能,往往会给新注册激活的用户一定的初始积分,每日签到/登录积分奖励等,在 Laravel 框架驱动的应用中,我们可以通过监听相应的事件来设置用户积分,下面我们就来简单演示其实现过程,并以此为例介绍用户注册登录事件监听及处理。
用户注册、登录和邮箱验证事件类 Laravel 框架底层已经提供,我们只需要通过事件监听器或订阅者来监听处理这些事件即可。
注:关于事件类的定义、监听和订阅,可以查看事件文档了解明细。
由于我们之前在模型事件教程中已经创建一个用户事件订阅者类 UserEventSubscriber,这里,我们在其基础上编写用户注册登录相关事件及其处理。
为用户表新增积分字段
要实现积分功能,首先需要新增一个数据库迁移类为用户表新增一个积分字段:
php artisan make:migration alter_users_add_point --table=users
编写对应的迁移文件代码如下:
integer('point')-> unsigned ()->default(0)->after('password');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('point');
});
}
}
登录到数据库所在环境,运行 php artisan migrate 让上述迁移生效。这样,users 表中就有 point 字段了:
新增用户积分日志表
此外,我们还要创建一张积分日志表,用于记录用户积分变更明细,通过如下命令创建积分日志模型类及对应迁移类:
php artisan make:model PointLog -m
该命令会创建一个 PointLog 模型类及对应数据库迁移文件,编写迁移文件代码如下:
increments('id'); $table->integer('user_id')->unsigned(); $table->tinyInteger('type')->unsigned()->comment('操作类型'); $table->smallInteger('value')->comment('积分变动值'); $table->timestamps(); $table->index('user_id'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('point_logs'); } }
登录到数据库所在环境,运行 php artisan migrate 让上述迁移生效。这样,就会在数据库中新增 point_logs 数据表。
然后在初始化 PointLog 模型类代码如下:
30, self::OPT_EMAIL_VERIFY => 20, self::OPT_USER_LOGIN => 5 ]; }
在该模型类中,我们主要设置了一些常量属性用于标识不同的操作类型,并定义了不同操作类型映射的积分变动值。对于本例而言,业务逻辑比较简单,所以通过一个静态属性数组来映射这个关系,对于复杂应用,映射值很多,这样做就不合适了,可以通过新增一张表来存储不同操作对应积分值,也方便管理。
定义模型类之间的关联关系
最后,我们还要在 User 模型类中通过如下方法定义其与 PointLog 之间的一对多关联:
public function pointLogs() { return $this->hasMany(PointLog::class); }
新用户注册
准备好数据结构之后,接下来,我们来处理事件监听。
用户注册对应的事件类是 Registered,对应事件类如下:
var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($user) { $this->user = $user; } }
该事件会在用户注册成功后触发,打开 UserEventSubscriber.php,在 subscribe 添加用户注册事件及对应的处理函数:
// 在文件顶部引入事件类完整命名空间 use Illuminate\Auth\Events\Registered; $events->listen( Registered::class, UserEventSubscriber::class . '@onUserRegistered' );
然后编写用户注册事件处理函数 onUserRegistered:
// 在文件定义引入 PointLog use App\PointLog; /** * 处理用户注册成功事件 * @param $event */ public function onUserRegistered($event) { // 用户注册成功后初始积分为30 $event->user->point += PointLog::$OPT_POINT[PointLog::OPT_USER_REGISTER]; $event->user->save(); // 保存积分变更日志 $pointLog = new PointLog(); $pointLog->type = PointLog::OPT_USER_REGISTER; $pointLog->value = PointLog::$OPT_POINT[PointLog::OPT_USER_REGISTER]; $event->user->pointLogs()->save($pointLog); }
这里,我们在用户注册成功后将其积分字段值初始化为注册奖励积分,并通过关联模型插入方式记录积分变更日志。
新用户邮箱验证
如果开启了邮箱验证功能,需要等到用户验证邮箱后,该用户才算真正激活,可以正常登录。验证邮箱事件框架底层也提供了,对应事件类是 Verified,实现代码如下:
user = $user; } }
该事件会在用户验证邮箱后触发,我们在订阅者 UserEventSubscriber 的 subscribe 方法中新增对该事件的订阅:
// 在文件顶部引入事件类完整命名空间 use Illuminate\Auth\Events\Verified; $events->listen( Verified::class, UserEventSubscriber::class . '@onEmailVerified' );
然后编写 onEmailVerified 方法来处理用户验证邮箱事件:
/** * 处理验证邮箱事件 * @param $event */ public function onEmailVerified($event) { // 用户验证邮箱后增加20积分 $event->user->point += PointLog::$OPT_POINT[PointLog::OPT_EMAIL_VERIFY]; $event->user->save(); // 保存积分变更日志 $pointLog = new PointLog(); $pointLog->type = PointLog::OPT_EMAIL_VERIFY; $pointLog->value = PointLog::$OPT_POINT[PointLog::OPT_EMAIL_VERIFY]; $event->user->pointLogs()->save($pointLog); }
验证邮箱后,为该用户新增 20 积分值,并记录积分变更日志。
用户每日登录
最后,我们来看用户登录事件的处理。用户登录事件类 Login 定义如下:
user = $user; $this->guard = $guard; $this->remember = $remember; } }
该事件会在用户登录成功后触发,同样,我们在订阅者 UserEventSubscriber 的 subscribe 方法中新增对该事件的订阅:
// 在文件顶部引入事件类完整命名空间 use Illuminate\Auth\Events\Login; $events->listen( Login::class, UserEventSubscriber::class . '@onUserLogin' );
然后编写事件处理函数 onUserLogin:
// 在文件顶部引入 Carbon use Carbon\Carbon; /** * 处理用户登录事件 * @param $event */ public function onUserLogin($event) { $pointLog = PointLog::where('user_id', $event->user->id)->where('type', PointLog::OPT_USER_LOGIN)->orderBy('created_at', 'desc')->first(); $firstLoginToday = false; if (!$pointLog) { // 注册后首次登录 $firstLoginToday = true; } else { $lastLoginTime = new Carbon($pointLog->created_at); if ($lastLoginTime->isYesterday()) { // 上次登录时间是昨天 $firstLoginToday = true; } } if ($firstLoginToday) { // 用户每日首次登录成功后增加5积分 $event->user->point += PointLog::$OPT_POINT[PointLog::OPT_USER_LOGIN]; $event->user->save(); // 保存积分变更日志 $pointLog = new PointLog(); $pointLog->type = PointLog::OPT_USER_LOGIN; $pointLog->value = PointLog::$OPT_POINT[PointLog::OPT_USER_LOGIN]; $event->user->pointLogs()->save($pointLog); } }
该处理函数相对复杂一点,因为我们只在每日首次登录才会对用户进行积分奖励,这个包含两种情况的判断,一种是用户首次登录,一种是上次登录时间是昨天,只有在这两种场景下,才会更新用户积分,同时记录积分变更日志。
测试用户登录注册流程积分变更
接下来,我们来演示一个新用户从注册到登录过程中的积分变更,并以此验证相应事件处理函数是否监听到对应事件并处理成功。
在浏览器访问新用户注册页面 ,填写注册表单:
点击注册按钮提交表单进行注册,页面跳转到邮箱验证页面:
说明注册成功。我们去查看 users 表和 point_logs 新增记录:
users 表中 point 字段值是 35,point_logs 中有两条记录,一条表示注册,一条表示登录,这意味着虽然邮箱未验证,但用户已经登录成功,只是未验证邮箱被中间件拦截,不能访问认证页面罢了。
下面我们来验证邮箱,登录到注册邮箱,在收件箱点开收到的验证邮件:
点击验证邮箱按钮进行验证,验证成功后会跳转到如下页面:
表示邮箱已验证,用户已激活,这个时候再到数据库查看 users 表和 point_logs 表记录:
会看到用户积分已变更,对应积分记录已生成,正是验证邮箱事件对应处理函数实现的。
为了验证用户每日登录只奖励一次积分,我们退出登录状态重新登录,如果用户积分没有变动,则表示代码是没有问题的。
点击了解更多去学习:非常使用的代码优化,怎么才能写好代码
相关文章
本站已关闭游客评论,请登录或者注册后再评论吧~