资讯专栏INFORMATION COLUMN

Laravel 5.4 入门系列 11. 通过邮件激活注册用户

dendoink / 2476人阅读

摘要:我们稍微封装下代码吧请您激活账户方法用于保存或更新字段方法用于判断是否在小时之内使用管理邮件在刚才的例子中,我们使用的是提供的方法来快速创建和发送邮件。

使用 Mailtrap 测试邮件功能

Mailtrap 提供了简单的测试邮件的服务,步骤如下:

登录网站 Mailtrap

注册用户

注册成功之后,会自动创建一个 demo,点进去之后就可以看到配置信息

只需要把上面的信息配置到对应的 .env 中即可:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=fc0ad24e593f34
MAIL_PASSWORD=aef271516bc810
MAIL_ENCRYPTION=null

这样,我们在应用里面发出去的邮件你都能在网站的 demo 中看到了。

用户激活功能实现 用户激活功能实现思路

接下来谈谈要实现的用户激活功能的基本过程:

创建数据表,保存用户激活信息;

提供激活选项给登录其未激活的用户;

用户点击激活之后,生成一个唯一的秘钥,保存到数据库;同时将秘钥以参数形式附在超链接的后面显示在用户邮箱正文中;

用户在邮箱中点击超链接,返回网站;

网站根据参数是否匹配以及是否过期(24小时)来判断用户是否激活成功;

创建数据表

因为激活的功能并不常用,将其多带带放置于一张表中:

$ php artisan make:model UserActivation -m

编辑字段:

/database/migrations/2017_04_21_071142_create_user_activations_table.php
 public function up()
{
    Schema::create("user_activations", function (Blueprint $table) {

        $table->integer("user_id")->unsigned()->primary();
        $table->string("token")->unique();
        $table->boolean("active")->default(0);
        $table->timestamps();

        $table->foreign("user_id")
              ->references("id")
              ->on("users")
              ->onDelete("cascade");
    });
}

执行:

$ php artisan migrate
添加用户表与用户激活表的一对一关系

用户表与用户激活表为一对一关系:

/app/User.php
public function activations()
{
    return $this->hasOne(AppUserActivation::class);
}

允许用户激活表批量赋值:

/app/UserActivation.php
protected $fillable= ["user_id","active","token"];
添加激活选项

首先,让登录且未激活的用户可以点击「激活」按钮:

/resources/views/layouts/nav.blade.php
@if (Auth::check())
    {{ Auth::user()->name }}
    登出
    @if (is_null(Auth::user()->activations) || Auth::user()->activations->active == 0)
        发送激活邮件
    @endif
@else            

路由指派该请求:

Route::get("/sendActivationMail","RegistrationController@send");

在实现具体的方法之前,我们先来介绍下如何快速发送邮件。

快速发送邮件

先来看看 Laravel 提供的选项:

$message->from($address, $name = null); # 邮件的所有者
$message->sender($address, $name = null); # 邮件的实际传输人,若所有者与发送者为同一人,可省略
$message->replyTo($address, $name = null); # 作者建议回复的地址
$message->to($address, $name = null); # 收件人的地址
$message->cc($address, $name = null); # 收件人外,想让其他知道该事的人的地址
$message->bcc($address, $name = null); # 不想让 cc 的人看到你发送给了谁,那么就用 bcc 

$message->subject($subject); #主题
$message->priority($level);
$message->attach($pathToFile, array $options = []);

注意,邮件的格式要遵守 RFC2822 规范,否则可能报错。

from            =       "From:" mailbox-list CRLF
sender          =       "Sender:" mailbox CRLF
reply-to        =       "Reply-To:" address-list CRLF
to              =       "To:" address-list CRLF
cc              =       "Cc:" address-list CRLF
bcc             =       "Bcc:" (address-list / [CFWS]) CRLF

我们举一个简单的例子:

public function send()
{   
    
    Mail::raw("test laravel blog email function",function ($message){
        $from = ["From: from@qq.com","fromman"];
        $to = ["To: to@qq.com","toman"];
        $cc = ["Cc: cc@qq.com","ccman"];
        $bcc = ["Bcc: bcc@qq.com","bccman"];
        $replyTo = ["Reply-To: replyto@qq.com","replytoman"];
        $sender = ["Sender: sender@qq.com","senderman"];
        $subject = "Subject Subject";
        $message->to($to)
                ->from($from)
                ->sender($sender)
                ->cc($cc)
                ->bcc($bcc)
                ->replyTo($replyTo)
                ->subject($subject);
    });

    return redirect("/");
}

raw 方法发送纯文本给对方。同时,我们在传入的闭包函数中进行配置。在本例子中,将会给 tomanccmanbccman 三个人一人发送一封纯文本邮件,因此,我们在 Mailtrap 中会收到三封:

因为 bcc 是密送,所以发送给 ccman 的邮件中看不到 bccman

在上述的配置字段中, from 字段以预先定义好,这样就不需要每次都填写了。当然,如果使用了 $message->from 方法,就会覆盖配置。

/config/mail.php
"from" => [
    "address" => env("MAIL_FROM_ADDRESS", ""From: "demo@blog.com"),
    "name" => env("MAIL_FROM_NAME", "Zen"),
],
激活功能实现

现在,我们实现可以发送激活邮件的功能了:

use AppUserActivation;

public function send()
{    
    // 生成唯一 token
    $token = bcrypt(auth()->user()->email.time());
    $user = auth()->user();
    
     // 发送邮件
    Mail::send("emails.activation", compact("user", "token"), function ($message) {
        $to = ["To: ".auth()->user()->email, auth()->user()->name];
        $subject = "blog demo 请您激活账户";

        $message->to($to)
                ->subject($subject);
    });
    
    
     // 数据库保存 token
    if ($user->activations){
        $user->activations()->update(["token"=>$token]);
    } else {
        $user->activations()->save(new UserActivation([
            "token" => $token
        ]));
    }
   
    // 发送并保存成功,跳转到主页
    return redirect("/");
}

这次,我们使用的是 Mail::send 方法,该方法可以传入视图作为邮件内容,同时第二个参数里传入给视图的数据,接下来定义视图:

/resources/views/emails/activation.blade.php



    
    Document


    

您好, {{ $user->name }} ! 请点击下面链接完成注册:

激活链接

用户将会收到这样的邮件:

点击链接之后,会向网站发送请求,路由进行指派:

Route::get("/activeAccount","RegistrationController@active");

最后,判断该 token 是否过期或者是否匹配,匹配则跳转到登录页面,否则跳转到主页。

use CarbonCarbon;
public function active()
{
    $token = request("verify");
    $rs = UserActivation::where("token", $token)
                        ->whereBetween("updated_at", [Carbon::now()->subDay(), Carbon::now()]);
    if ($rs->exists()) {
        $rs->update(["active"=>true]);
        return redirect("/login");
    }

    return redirect("/");
}

功能已经实现了。我们稍微封装下代码吧:

/app/Http/Controllers/RegistrationController.php
public function send()
{
    $token = bcrypt(auth()->user()->email.time());
    $user = auth()->user();

    Mail::send("emails.activation", compact("user", "token"), function ($message) {
    
        $to = ["To: ".auth()->user()->email, auth()->user()->name];
        $subject = "blog demo 请您激活账户";

        $message->to($to)
                ->subject($subject);
    });


    $user->addActivationsData($token);
   
   
    return redirect("/");
}

public function active()
{
    $token = request("verify");
    $rs = UserActivation::where("token", $token)
                        ->notExpired();

    if ($rs->exists()) {
        $rs->update(["active"=>true]);
        return redirect("/login");
    }

    return redirect("/");
}

addActivationsData 方法用于保存或更新 $token 字段:

/app/User.php
public function addActivationsData($token)
{   
    if ($this->activations) {
        $this->activations()->update(["token"=>$token]);
    } else {
        $this->activations()->save(new AppUserActivation([
            "token" => $token
        ]));
    }
}

notExpired 方法用于判断 token 是否在 24 小时之内:

/app/UserActivation.php
use CarbonCarbon;
public function scopeNotExpired($query)
{
    return $query->whereBetween("updated_at", [Carbon::now()->subDay(), Carbon::now()]);
}
使用 mailables 管理邮件

在刚才的例子中,我们使用的是 Mail 提供的方法来快速创建和发送邮件。实际上,Laravel 提供了管理不同类型邮件的方法。我们来快速了解下。

创建「欢迎」邮件类型

首先,我们来创建一个用于欢迎新用户的 mailables:

$ php artisan make:mail Welcome

首次使用时,会创建 app/Mail 目录。接下来,我们就可以实现给用户发送欢迎邮件的功能了。

首先,用户注册成功之后,发送一封欢迎邮件:

/app/Http/Controllers/RegistrationController.php
use AppMailWelcome;
public function store()
{
    ...
    
    auth()->login($user);

    Mail::to($user)->send(new Welcome);

    return redirect()->home();
}

之前我们通过闭包的方式传递 fromto 等字段,实际上,也可以直接将 $user 实例直接传递给 to,这样会自动去识别 namefrom 字段。然后,send 方法传入 mailables 类即可。

如果使用 to($user) 可能会报错,因为不符合我们之前说的 RFC2822 规范。

配置 mailables

接下来,发送邮件的主要功能都可以在定义的 Welcome 类中实现了。

可以定义邮件的 blade 视图:

/app/Mail/Welcome.php
public function build()
{   
    return $this->view("emails.welcome");
}

显示结果为:

也可以定义纯文本视图:

/app/Mail/Welcome.php
public function build()
{   
    
    return $this->text("emails.welcome");
}

对应的视图文件如下:

/resources/views/emails/welcome.blade.php



    
    Document


    

{{$name}}, 欢迎成为 Blog Demo 的会员

可以配置邮件的各种信息,跟之前的方式类似:

public function build()
{   
    $from = ["From: from@qq.com","fromman"];
    $to = ["To: to@qq.com","toman"];
    $subject = "Subject Subject";

    return $this->text("emails.welcome")
                ->to($to)
                ->from($from)
                ->subject($subject);

}

可以传递变量给视图,第一种是直接在 view 里面传递(也可以使用 with):

/app/Mail/Welcome.php
public function build()
{   
    $from = ["From: from@qq.com","fromman"];
    $to = ["To: to@qq.com","toman"];
    $subject = "Subject Subject";
    $user = auth()->user();
    return $this->view("emails.welcome",compact("user"))
                ->to($to)
                ->from($from)
                ->subject($subject);


}

/resources/views/emails/welcome.blade.php

{{$user->name }}, 欢迎成为 Blog Demo 的会员

另外一种方法是,在 Welcome 类中定义属性类型为「公共的」。这样该属性就会自动传递给视图:

/app/Http/Controllers/RegistrationController.php
Mail::send(new Welcome);

/app/Mail/Welcome.php
public $user;

public function __construct(User $user)
{
    $this->user = $user;
}

最后,我们还可以使用 Markdown 的语法来写邮件:

$ php artisan make:mail MDWelcome --markdown="emails.md-welcome"

创建使用使用 --markdown 参数来生成对应的视图即可。具体使用方法可以查看文档。


参考资料:

RFC2822 中文文档

Laravel 的 邮件发送功能 | Laravel 5.4 中文文档

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22824.html

相关文章

  • Laravel 5.4 入门系列 12. 使用请求类进行字段验证

    摘要:本节内容比较简单,之前我们使用方法来进行字段验证,这样做有一个不好的地方就是,如果你要在很多地方使用同样的验证,就需要重复编写代码。因此,提供另外一种方式来进行字段验证,即请求类。 本节内容比较简单,之前我们使用 validator 方法来进行字段验证,这样做有一个不好的地方就是,如果你要在很多地方使用同样的验证,就需要重复编写代码。因此,Laravel 提供另外一种方式来进行字段验证...

    BearyChat 评论0 收藏0
  • Laravel 5.4 入门系列 9. 注册与登录,用户关联

    摘要:本节将实现文章评论与用户关联的功能。关系定义首先修改与表,增加字段增加全部回滚并重新执行迁移添加用户表与文章表评论表的一对多关系添加文章评论表与用户表的多对一关系同时,评论表的字段增加。同时,我们还自定义了返回的错误信息。 本节将实现文章、评论与用户关联的功能。 关系定义 首先修改 posts 与 comments 表,增加 user_id 字段 /database/migratio...

    smallStone 评论0 收藏0
  • Laravel 5.4 入门系列 10.文章归档

    摘要:将上述的一系列查询进行封装模型到了这一步,我们基本上实现了文章归档的功能。但是有一个问题,文章归档实际上包括在通用视图中,这就意味着,网站的所有请求都需要返回,否则就会报错。数据库之数据库请求构建器中文文档的视图功能中文文档 首先,要实现的是按照日期来统计文章,原始的 SQL 如下: select year(created_at) year, monthname(c...

    Nekron 评论0 收藏0
  • Laravel 5.4 入门系列 4. 任务列表显示(2)

    摘要:同时,传入参数,即已存在的查询。因此,更为常见的做法是在控制器中处理路由请求。 这一节,我们进一步完善上一节创建的任务列表。主要知识点: Eloquent Model 控制器 路由模型绑定 Eloquent Model 新增迁移 首先,我们为数据库表 tasks 新增一个字段 completed,用来表示任务是否完成: $ php artisan make:migration ad...

    banana_pi 评论0 收藏0
  • Laravel 5.4 正式发布

    摘要:它的目的是提供正确的方式进行页面交互测试,所以可以使用去点击按钮或者链接填写表单甚至拖放。此外,提到测试运行比更快。此次因底层架构改变较大而重命名。这个功能受到的启发,能够将元素简化为可重用区域。 showImg(https://segmentfault.com/img/remote/1460000008212617); 转自 Laravel 社区:https://laravel-ch...

    Vultr 评论0 收藏0

发表评论

0条评论

dendoink

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<