【Laravel-海贼王系列】第十五章,Model Observer 解析

简介

能够替代数据库的触发器功能。laravel

Observer 的建立

观察者的功能来自与继承的 Model 对象的 trait HasEvents 特质。数据库

本章咱们使用 Laravel 默认的 User 模型来进行说明。数组

建立一个观察者类bash

注册 Observer

经过 provider 来注册 Observeride

关于 provider 加载机制能够移步【Laravel-海贼王系列】第八章, Provider 功能解析post

观察过程解析

User::observe() 方法来自 Illuminate\Database\Eloquent\Concerns\HasEvents;ui

上面介绍过了,这个特质类是关键,我也主要围绕这个类来分析。this

public static function observe($classes)
{
    // "指向 User 对象"
    $instance = new static;

    // "支持一次传入数组或者字符串的型式统一包装成数组"
    // "这里能够看出 observe() 方法支持一次观察多个类"
    foreach (Arr::wrap($classes) as $class) {
        
        $instance->registerObserver($class);
    }
}
复制代码

展开 $instance->registerObserver($class);spa

// "刚才的传入 $class = 'App\UserObserver'"
protected function registerObserver($class)
{
    $className = is_string($class) ? $class : get_class($class);

    // "这里就是获取指定的事件名称"
    $this->getObservableEvents()  = array_merge(
        [
            'retrieved', 'creating', 'created', 'updating', 'updated',
            'saving', 'saved', 'restoring', 'restored',
            'deleting', 'deleted', 'forceDeleted',
        ],
        $this->observables, // "这个是提供给用户本身定义的方法"
    );

    foreach ($this->getObservableEvents() as $event) {

        // "还记得 'App\UserObserver' 中定义的方法吗!"
    
        if (method_exists($class, $event)) {
            static::registerModelEvent($event, $className.'@'.$event);
        }
    }
}
复制代码

注册 Observer 中的事件

上面循环了全部的提早指定事件,而后逐个检查观察者并进行注册。rest

继续分析 static::registerModelEvent($event, $className.'@'.$event);

protected static function registerModelEvent($event, $callback)
{
    if (isset(static::$dispatcher)) {
        $name = static::class;

        static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
    }
}
复制代码

statci::$dispatcherlluminate\Events\Dispatcher 对象

因此其实这里迭代调用了,能够看到就是绑定一个个事件,同时将事件 指向UserObserver@functionName的对应方法中。

static::$dispatcher->listen("eloquent.retrieved: App\User", 'App\UserObserver@retrieved');
static::$dispatcher->listen("eloquent.creating: App\User", 'App\UserObserver@creating');
static::$dispatcher->listen("eloquent.created: App\User", 'App\UserObserver@created');
..... 省略相似代码
static::$dispatcher->listen("eloquent.forceDeleted: App\User", 'App\UserObserver@forceDeleted');
复制代码

关于事件的绑定以及触发机制请移步【Laravel-海贼王系列】第九章, Events 功能解析

经历过上面种种绑定咱们已经绑定了须要的事件,而且监听者就是 UserObserver 对象。

接下来就是如何触发的问题了。

触发 Observer 监听的事件

咱们来看经常使用的生成用户的方法。

User::create(
    [
        'name'     => "big pig's feet",
        'email'    => 'hello@world.com',
        'password' => password_hash('123456', PASSWORD_BCRYPT, ['cost' => 12,]),
    ]
);
复制代码

⚠️这里 create 方法在 Model 中并不存在,会调用魔术方法 __call()

咱们本章只关心观察者,查询构建器后续在涉及!直接看最终调用方法

位于 ModelperformInsert 方法

protected function performInsert(Builder $query)
{
    if ($this->fireModelEvent('creating') === false) {
        return false;
    }
    
    if ($this->usesTimestamps()) {
        $this->updateTimestamps();
    }

    $attributes = $this->getAttributes();

    if ($this->getIncrementing()) {
        $this->insertAndSetId($query, $attributes);
    }else {
        if (empty($attributes)) {
            return true;
        }

        $query->insert($attributes);
    }
    
    $this->exists = true;

    $this->wasRecentlyCreated = true;

    $this->fireModelEvent('created', false);

    return true;
}
复制代码

这里咱们不详解如何执行事件的代码,咱们只关心执行了什么!

执行逻辑分析:

首先触发模型以前绑定的 creating 方法。

调用最后插入数据的逻辑。

设置一些放重复的属性

调用绑定的 created 事件。

到了这里能够知道官方给出的许多事件以及执行顺序的缘由!

结语

LaravelModel 功能很是多,本章只是

简单的介绍了其中一种功能“观察者”,还有不少方法没有分析

可是基本原理咱们只要知道一种其余也都是同样。

最后总结一下

Model 结合 laravel 事件来完成观察者事件的监听和触发。

Provider 提供了观察者在启动过程的加载服务。

相关文章
相关标签/搜索