模型事件的触发时机

模型事件:

模型事件:retrieved、creating、created、updating、updated、saving、saved、deleting、deleted、restoring、restored。

L02中的使用场景:

  1. SEO 友好的 URL:
  • TopicObserver::saving();
  • 入库前对 slug 字段进行赋值。
  1. 实现对评论的计数:
  • ReplyObserver::created();
  • 每增加一条评论,就需要重新对评论数统计。
  1. 对评论进行过滤。(防御 XSS 攻击)
  • ReplyObserver::creating();
  • 过滤评论中的 JS 脚本。
  1. 用户回复主题后,通知到主题作者。
  • ReplyObserver::created();
  • 当用户回复发布成功后,就通知主题的作者。
  1. 实现对评论的计数
  • ReplyObserver::deleted();
  • 用户删除回复后,需要重新统计回复数。
  1. 话题连带删除
  • TopicObserver::deleted();
  • 当删除了话题时,需要将该话题下的所有评论都删除。

问题

模型事件有11个,分为 ed 和 ing 两种。跟着教程敲代码的时候感觉不难,但是如果要自己在特定的场景下使用正确的模型事件很难。因为我并没有找到背后的规律,只是知道了几种特例。今天看了一天的文章,码源也看了不少,但是感觉迷迷糊糊的。看累了,躺在床上思考了一下,发现自己的目的不明确
今天我主要想解决:
如何正确的使用模型事件来达到自己的目的。而不是模型事件的实现原理。而我今天看的码源大多数和模型事件的实现原理有关,所以感觉摸不着边。而且现在自己的道行太浅,看码源有点吃力,模型事件的实现原理以后再说吧。

save 方法

明确了自己的目的,看文章就能抓住重点了。在laravel Eloquent save 触发了哪些事件一文中,找到了线索。正确使用模型事件的关键就在于需要知道模型事件的触发时机。
laravel Eloquent save 触发了哪些事件一文可知,调用 Model::save() 方法时,就会触发大多数常见的模型事件。因为在调用 Model::update() 方法时,最终还是会调用 Model::save()。
Model::update()码源如下:

<?php
...
abstract class Model ...
...
public function update(array $attributes = [], array $options = [])
{
    if (! $this->exists) {
        return false;
    }
    // 这里调用了 save 方法。
    return $this->fill($attributes)->save($options);
}
...

所以只要把 Model::save() 方法理清了,就能把大多数事件模型的触发时机搞清楚。但是laravel Eloquent save 触发了哪些事件一文讲的很清楚,就不再赘述了(炒冷饭也没意思)。直接上结论:

  1. 触发顺序
    • 新创建的对象,save 依次触发 saving=>creating=>created=>saved;
    • 已存在的对象,save 依次触发 saving=>updating=>updated=>saved;
  2. 触发时机:
    • saving模型事件触发于 Model::save() 方法被调用后。
    • 如果模型还未创建:
      • creating模型事件触发于入库前。
      • created 模型事件触发于入库后。
    • 如果模型已经存在:
      • updating模型事件触发于更新前。
      • updated 模型事件触发于更新后。

delete 方法

当调用 delete 方法时,如果一切正常,就会触发 deleting 和 deleted 模型事件。Model::delete() 方法码源如下:

<?php
...
abstract class Model ...
...
public function delete()
{
    $this->mergeAttributesFromCachedCasts();

    if (is_null($this->getKeyName())) {
        throw new LogicException('No primary key defined on model.');
    }

    // If the model doesn't exist, there is nothing to delete so we'll just return
    // immediately and not do anything else. Otherwise, we will continue with a
    // deletion process on the model, firing the proper events, and so forth.
    if (! $this->exists) {
        return;
    }

    if ($this->fireModelEvent('deleting') === false) {
        return false;
    }

    // Here, we'll touch the owning models, verifying these timestamps get updated
    // for the models. This will allow any caching to get broken on the parents
    // by the timestamp. Then we will go ahead and delete the model instance.
    $this->touchOwners();

    $this->performDeleteOnModel();

    // Once the model has been deleted, we will fire off the deleted event so that
    // the developers may hook into post-delete operations. We will then return
    // a boolean true as the delete is presumably successful on the database.
    $this->fireModelEvent('deleted', false);

    return true;
}
...

跟着注释理一遍过程:

  1. 如果模型存在,就会触发 deleting 模型事件。
  2. 一旦模型被删除了,就会触发 deleted 模型事件。
    小节:
  3. 触发顺序:
    • deleting=>deleted;
  4. 触发时机:
    • deleting 模型事件触发在模型被删除之前。
    • deleted 模型事件触发在模型删除之后。

教训

在学习的时候,一定要把目的搞清楚了,不然学了半天都不知道自己在干啥。

参考

  1. Laravel 模型事件入门
  2. Laravel 中的模型事件与 Observer
  3. laravel Eloquent save 触发了哪些事件
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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