如何使用 Laravel 为每个模型实例注册一个默认的观察者

Álv*_*ães 6 php laravel laravel-5.1

Laravel 5.1

我正在尝试为每个扩展我的 AbstractModel 的模型(正在扩展 Illuminate\Database\Eloquent\Model)注册一个模型观察者。

问题是我的 GenericModelObserver 无法侦听由继承 AbstractModel 的模型触发的事件。

让我展示我到目前为止所做的事情。

创建了一个服务提供者并将其放在 config/app.php 中提供者数组的最后一个位置

<?php

// app/Providers/ObserverServiceProvider.php

namespace App\Providers;

use App\Models\Quotation;
use App\Models\AbstractModel;
use App\Observers\QuotationObserver;
use App\Observers\GenericModelObserver;
use Illuminate\Support\ServiceProvider;

class ObserverServiceProvider extends ServiceProvider
{

    public function boot()
    {
        AbstractModel::observe(GenericModelObserver::class);
        Quotation::observe(QuotationObserver::class);
    }

    public function register()
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

然后我有我简单的 GenericModelObserver

<?php

// app/Observers/GenericModelObserver.php

namespace App\Observers;

use App\Models\AbstractModel;

class GenericModelObserver
{
    public function saving(AbstractModel $model)
    {
        return $model->valid();
    }
}
Run Code Online (Sandbox Code Playgroud)

抽象模型

<?php

// app/Models/AbstractModel.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class AbstractModel extends Model
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

我的报价模型

<?php

// app/Models/Quotation.php

namespace App\Models;

class Quotation extends AbstractModel
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

保存 Quotation 时,GenericModelObserver 无法侦听保存事件或任何其他事件。

这同样适用于没有特定模型观察者的其他模型。

这是正确的策略吗?我不想通过 boot 方法将观察者绑定到每个模型。

Gie*_*šys 7

而不是扩展模型 - 编写您自己的特征,它将作为观察者工作。
下面我写了一些基本特征:

<?php

namespace App\YourPackage\Traits;

use Illuminate\Database\Eloquent\Model;

trait Observable
{
    public static function bootObservable()
    {
        static::updating(function (Model $model) {
            dd('updating');
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

并通过键入use Observable;您的模型类来使用它。

另外,为了您的学习,请注意 trait 是如何启动的:您必须将boot[TraitClassName]方法放入 trait,以正确启动它。
永远不要boot在你的 trait 中写方法,这很危险!


小智 5

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Observers\TeamObserver;

class Team extends Model
{
    /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        self::observe(TeamObserver::class);
    }
}
Run Code Online (Sandbox Code Playgroud)


Eme*_*bah 3

为什么不简单地扩展一个父类呢BaseObserver

我的缓存系统中有类似的东西

<?php namespace App\Observers;
class BaseObserver {
    public function saving($model)
    {
        //do your thing here that apply to all observers, like caching
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的Observers

<?php namespace App\Observers;
class Quotation extends BaseObserver{
   //you can override any of the methods if you wish
}
Run Code Online (Sandbox Code Playgroud)