简单的介绍 Eloquent 模型生命周期

@这是小豪的第七篇文章

在没有接触 Laravel 的时候,都还不知道 PHP 有事件、模型生命周期这一说,一直都是什么时候需要什么时候调用,代码写的一大坨,哈哈,今天带大家来看看 Eloquent 模型生命周期到底是什么样子的什么时候使用。

准备

我们以文章为例子:

class Post extends Model
{
    protected $fillable = [
        'user_id', 'title', 'content',
    ];

    protected $casts = [
        'id' => 'int',
        'user_id' => 'int',
    ];

    protected static function boot()
    {
        parent::boot(); // TODO: Change the autogenerated stub

        static::retrieved(function (Post $post) {
            echo 'This is retrieved' . "\n";
        });

        static::creating(function (Post $post) {
            echo 'This is creating' . "\n";
        });

        static::created(function (Post $post) {
            echo 'This is created' . "\n";
        });

        static::updating(function (Post $post) {
            echo 'This is updating' . "\n";
        });

        static::updated(function (Post $post) {
            echo 'This is updated' . "\n";
        });

        static::saving(function (Post $post) {
            echo 'This is saving' . "\n";
        });

        static::saved(function (Post $post) {
            echo 'This is saved' . "\n";
        });

        static::deleting(function (Post $post) {
            echo 'This is deleting' . "\n";
        });

        static::deleted(function (Post $post) {
            echo 'This is deleted' . "\n";
        });
    }
}

创建文章

public function store(Request $request)
{
    $post = Post::create(['title' => '这是文章标题', 'content' => '这是文章内容', 'user_id' => Auth::id()]);

    return \response()->json($post);
}

此时我们可以看到输出的顺序依次为:

1 2 3 4
This is saving This is creating This is created This is saved

更新文章

public function update(Request $request)
{
    $post = Post::find(1);

    $post->title = '这是更新的文章标题';

    $post->save();

    return \response()->json($post);
}

此时我们可以看到输出的顺序依次为:

1 2 3 4 5
This is retrieved This is saving This is updating This is updated This is saved

从简单的更新与创建中,大家可以看到触发的事件中多了一个 retrieved ,以及 creatingcreated 依次变为了 updatingupdated,其余的都是保持一致的。多出来的 retrieved 是从哪里蹦出来的呢,我们看看文档中给出的解释:

“当从数据库检索现有模型时,会触发retrieved 事件”

其实我刚才看到这句话的时候有点蒙,啥呀,哈哈。下面简单给大家再演示一遍看看:

public function test()
{
    $post = Post::find(1);

    // 输出:This is retrieved

    $post = Post::create(['title' => '这是文章标题 2 ', 'content' => '这是文章内容 2 ', 'user_id' => Auth::id()]);

    // 输出:.....

    $posts = Post::all();

    // 输出:This is retrieved、This is retrieved
}

大家有没有看出啥子端倪,哈哈,一条记录触发了一次。

删除文章

public function destroy(Request $request)
{
    $post = Post::find(1);

    $post->delete();
}

此时我们可以看到输出的顺序依次为:

1 2 3
This is retrieved This is deleting This is deleted

批量更新

public function test(Request $request)
{
    Post::where('id' ,'>' ,0)->update(['title' => '这是文章标题更新', 'content' => '这是文章内容', 'user_id' => 1]);
}

此时我们可以看到没有输出,为啥呢?通过 Eloquent 进行批量更新时,不会为更新的模型触发 saved 和 updated 模型事件。这是因为在进行批量更新时,并未检索该模型。

批量删除

public function test(Request $request)
{
    Post::where('id' ,'>' ,0)->delete();
}

也是一样没有输出的噢,哈哈。

结束语

大家可能会问啥时候会用到这些模型事件呢,举例一些给大家看看:

    protected static function boot()
    {
        parent::boot(); // TODO: Change the autogenerated stub

        static::retrieved(function (Post $post) {
            // 文章加精
            \dispatch(new PostAddPopular($post));
        });

        static::creating(function (Post $post) {
            $post->user_id = Auth::id();
        });

        static::saving(function (Post $post) {
            // 敏感词过滤
            $post->title = \dispatch_now(new FilterThreadSensitiveWords($post->title));
        });
    }

    ......

等等还有好多妙用,大家可以结合自己的需求对生命周期完美的利用哈哈。

也可以定义一个观察者进行监听处理的,不过没有很大处理量的时候,还是建议这种直接在模型中定义的方式噢。

本作品采用《CC 协议》,转载必须注明作者和本文链接
finecho # Lhao
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

棒棒棒~~~~谢谢

5年前 评论

有个问题,这种没法触发update事件
User::where('id',1)->update(['name'=>'test'])

4年前 评论
finecho

@lovecn 批量更新是不会触发事件的噢,哪怕只是 where('id', 1) ,User::find(1)->update(['name' => 'test']); 这样才会触发事件噢。

4年前 评论

楼主能分享一下FilterThreadSensitiveWords的实现吗

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!