我正在尝试为扩展我的AbstractModel的每个模型注册一个模型观察者(他们正在扩展Illuminate \ Database \ Eloquent \ Model)。
问题是我的GenericModelObserver无法侦听继承AbstractModel的模型触发的事件。
让我展示一下我到目前为止做了什么。
创建了一个服务提供程序,并将其放在config / app.php
中的providers数组的最后一个位置<?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()
{
}
}
然后我有简单的GenericModelObserver
<?php
// app/Observers/GenericModelObserver.php
namespace App\Observers;
use App\Models\AbstractModel;
class GenericModelObserver
{
public function saving(AbstractModel $model)
{
return $model->valid();
}
}
抽象模型
<?php
// app/Models/AbstractModel.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AbstractModel extends Model
{
// ...
}
我的报价模型
<?php
// app/Models/Quotation.php
namespace App\Models;
class Quotation extends AbstractModel
{
// ...
}
保存报价时,GenericModelObserver无法收听保存事件或任何其他事件。
这同样适用于没有特定模型观察者的其他模型。
这是正确的策略吗?我不想通过引导方法将观察者绑定到每个模型。
答案 0 :(得分:3)
而不是扩展模型 - 编写自己的特征,作为观察者 下面我写了一些基本特征:
<?php
namespace App\YourPackage\Traits;
use Illuminate\Database\Eloquent\Model;
trait Observable
{
public static function bootObservable()
{
static::updating(function (Model $model) {
dd('updating');
});
}
}
并在模型类中键入use Observable;
来使用它。
同样为了您的学习,请记录特征是如何启动的:您必须将boot[TraitClassName]
方法置于特征中,才能正确启动。
永远不要在你的特质中写boot
方法,这很危险!
答案 1 :(得分:2)
为什么不简单地扩展父类说List
我的缓存系统中有类似内容
BaseObserver
然后在<?php namespace App\Observers;
class BaseObserver {
public function saving($model)
{
//do your thing here that apply to all observers, like caching
}
}
Observers
答案 2 :(得分:0)
在您的父模型中,您可以执行类似的操作
/**
* If true will attach the observers of the parent class
* @var bool
*/
protected $shouldAttachParentObservers = true;
public static function boot()
{
$instance = new static;
$instance->attachParentObservers();
parent::boot();
}
public function attachParentObservers() {
$parentClass = get_parent_class($this);
if(!empty($parentClass) && $this->shouldAttachParentObservers) {
$eventObservers = [];
foreach ($this->getObservableEvents() as $event) {
$eventObservers[$event] = ($this::$dispatcher->getListeners("eloquent.{$event}: {$parentClass}"));
foreach ($eventObservers[$event] as $observer) {
$eventName = "eloquent.{$event}: {$this::getClassName()}";
$this::$dispatcher->listen($eventName, $observer);
}
}
}
}
/**
* You may use different way to find the class name
*/
public static function getClassName() {
return static::class;
}
答案 3 :(得分:0)
将boot
中的AppServiceProvider
方法更新为以下内容:
public function boot()
{
# Register all model observers
$filesInFolder = \File::files(app_path('/Observers'));
foreach($filesInFolder as $path) {
$observerClassName = pathinfo($path)['filename'];
$className = str_replace('Observer', '', $observerClassName);
$observerClassName = 'App\\Observers\\' . $observerClassName;
$className = 'App\\' . $className;
$className::observe($observerClassName);
}
}
模型应遵循以下格式:
App\User
观察者应遵循以下格式:
App\Observers\UserObserver
答案 4 :(得分:0)
<?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);
}
}