laravel Eloquent save 触发了哪些事件

Laravel 104℃ 0评论

码农宅
需求是这样的,如果在订单状态改变的时候给对应的用户发送消息

  • 当然第一个想到的就是用Eloquent的事件,订单状态变了,会触发事件,但是Eloquent的这些updated,saved事件怎么知道是订单状态变了,而不是其他值改变了触发的呢?消息里面需要用到订单原来的属性怎么办?
  • 或者就是controller处理完逻辑,改变了订单的状态自己触发一个事件,那么是不是触发事件需要传入原来的订单的属性和改变后的属性呢?这样listener才能确切的知道订单的状态是怎么变得,然后发送对应的消息?
  • 或者压根不触发事件,直接在controller中处理这个逻辑,因为controller明白到底发生了什么,直接发送消息,想怎么发怎么发

我们有好多好多的订单,好多好多的地方会改变订单状态,显然2,3两个方案太扯淡了,每个处理逻辑的地方都需要增加代码,处理一堆逻辑,写着就不爽,维护起来不是要疯了?

好吧我们来看看laravel Eloquent save的时候到底触发了哪些事件

Illuminate/Database/Eloquent/Model.php
 public function save(array $options = [])
 {
     $query = $this->newQueryWithoutScopes();
     if ($this->fireModelEvent('saving') === false) {
         return false;
     }
     if ($this->exists) {
         $saved = $this->performUpdate($query, $options);
     } else {
         $saved = $this->performInsert($query, $options);
     }
     if ($saved) {
         $this->finishSave($options);
     }
     return $saved;
 }

首先触发的当然是saving,如果saving返回的是false,那么save就失败了,返回false

接着如果$this->exists,就是这个model不是新创建的,那么就需要进行更新操作

protected function performUpdate(Builder $query, array $options = [])
{
    $dirty = $this->getDirty();
    if (count($dirty) > 0) {
        if ($this->fireModelEvent('updating') === false) {
            return false;
        }
        if ($this->timestamps && Arr::get($options, 'timestamps', true)) {
            $this->updateTimestamps();
        }
        $dirty = $this->getDirty();
        if (count($dirty) > 0) {
            $numRows = $this->setKeysForSaveQuery($query)->update($dirty);
            $this->fireModelEvent('updated', false);
        }
    }
    return true;
}

看看更新干了什么,

  • 首先如果这个模型dirty了,也就是脏了,也就是有属性改变了,那么才需要更新
  • 先触发updating,更新失败了就false,
  • 更新时间戳
    这里又判断了count($dirty) > 0,为什么??更updateTimestamps有什么关系吗?没有仔细看,以后再说吧
  • 然后执行update,也就是写入了数据库
  • 最后触发updated
    那么如果这个对象是新建的,也就是需要执行插入操作,performInsert也做了差不多的事,
  • 触发creating,
  • 执行insert,插入数据库,
  • 最后created。
    最后回到save方法,如果更新或者插入操作成功了,那么就finishSave来结束save,
    finishSave 触发了saved事件, 最后syncOriginal。

小结一下

  • 新创建的对象,save依次触发 saving->creating->created->saved
  • 已存在的对象,save依次触发 saving->updating->updated->saved

这就需要看看isDirty和syncOriginal是怎么回事了

打印过Eloquent 对象的应该都会发现,其实模型会有两个数组,一个original,一个attributes。

这下应该就明白了,初始化一个模型的时候这两个数组是一样的,赋值操作只是改变attributes,所以isDirty也就是根据两个数据来判断模型是否dirty了,模型触发完saved事件后才会执行syncOriginal,syncOriginal也就是将attributes赋值给original。所以上面触发的所有事件,我们都是能拿到原来的值和变化的值得。

所以我们的问题也就解决了,当模型触发updated事件的时候,我们根据isDirty([‘status’]) 知道订单状态改变了,然后拿到订单之前是个什么样子,改变后是个什么样子,该发什么消息也就很明朗了。

转载请注明:码农宅 » laravel Eloquent save 触发了哪些事件

喜欢 (0)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址