我有一个有更新方法的观察者:
ObserverServiceProvider.php
public function boot()
{
Relation::observe(RelationObserver::class);
}
RelationObserver.php
public function updated(Relation $relation)
{
$this->cache->tags(Relation::class)->flush();
}
所以当我更新控制器中的关系时:
public function update(Request $request, Relation $relation)
{
$relation->update($request->all()));
return back();
}
一切都按预期工作 . 但现在我有了一个数据透视表 . relation belongsToMany
产品 .
所以现在我的控制器方法如下所示:
public function update(Request $request, Relation $relation)
{
if(empty($request->products)) {
$relation->products()->detach();
} else {
$relation->products()->sync(collect($request->products)->pluck('id'));
}
$relation->update($request->all());
return back();
}
问题是如果我添加或删除产品,观察者不再被触发 .
pivot table
更新时如何触发观察者?
谢谢
1 回答
如您所知,Laravel在调用
sync()
时实际上并不检索模型或在任何模型上调用save / update,因此默认情况下不会创建任何事件 . 但我想出了一些替代解决方案来解决你的问题 .1 - 为sync()方法添加一些额外的功能:
如果深入了解
belongsToMany
功能,您将看到它尝试猜测某些变量名称并返回BelongsToMany对象 . 最简单的方法是让你的关系函数自己简单地返回一个自定义BelongsToMany
对象:或者,复制整个函数,重命名并使其返回
BelongsToManySpecial
类 . 或者省略所有变量,或者简单地返回new BelongsToManyProducts
类并解析__construct
中的所有BelongsToMany变量......我想你明白了 .使BelongsToManySpecial类扩展原始的BelongsToMany类,并将同步函数写入BelongsToManySpecial类 .
或者覆盖
detach
和attachNew
函数以获得类似的结果 .如果你想深入挖掘并想要了解幕后发生的事情,那么分析
Illuminate\Database\Eloquent\Concerns\HasRelationship
特征 - 特别是belongsToMany
关系函数和BelongsToMany
类本身 .2 - 创建一个名为
BelongsToManySyncEvents
的特征,它不会比返回特殊的BelongsToMany类做更多的事情创建
BelongsToManyWithSyncEvents
类:现在将特征添加到您的 class .
3 - 结合以前的解决方案,并将此功能添加到BaseModel类等中的每个模型中 . 例如,如果定义了它们,请检查并调用某些方法...
4 - 创建服务
在该服务内部创建一个必须始终调用的函数,而不是默认的
sync()
. 也许称之为attachAndDetachProducts(...)并添加您的事件或功能由于我没有关于你的课程和关系的那么多信息,你可以选择比我提供的更好的课程名称 . 但是,如果您现在的用例只是清除缓存,那么我认为您可以使用一些提供的解决方案 .