gpt4 book ai didi

php - 数据透视表的 Laravel 观察者

转载 作者:行者123 更新时间:2023-12-01 03:24:06 27 4
gpt4 key购买 nike

我有一个具有更新方法的观察者:

ObserverServiceProvider.php

public function boot()
{
Relation::observe(RelationObserver::class);
}

RelationObserver.php
public function updated(Relation $relation)
{
$this->cache->tags(Relation::class)->flush();
}

因此,当我更新 Controller 中的关系时:
public function update(Request $request, Relation $relation)
{
$relation->update($request->all()));
return back();
}

一切都按预期工作。但现在我有一个数据透视表。 关系 belongsToMany 产品。

所以现在我的 Controller 方法如下所示:
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 更新 aswel 时,如何触发观察者?

谢谢

最佳答案

如您所知,Laravel 在调用 sync() 时实际上不会检索模型,也不会调用任何模型的保存/更新,因此默认情况下不会创建任何事件。但是我为您的问题提出了一些替代解决方案。

1 - 向 sync() 方法添加一些额外的功能:

如果您深入研究 belongsToMany 功能,您将看到它尝试猜测一些变量名称并返回一个 BelongsToMany 对象。最简单的方法是让你的关系函数自己简单地返回一个自定义的 BelongsToMany 对象:

public function products() {

// Product::class is by default the 1. argument in ->belongsToMany calll
$instance = $this->newRelatedInstance(Product::class);

return new BelongsToManySpecial(
$instance->newQuery(),
$this,
$this->joiningTable(Product::class), // By default the 2. argument
$this->getForeignKey(), // By default the 3. argument
$instance->getForeignKey(), // By default the 4. argument
null // By default the 5. argument
);
}

或者复制整个函数,重命名它并使其返回 BelongsToManySpecial 类。或者省略所有变量,也许只是返回 new BelongsToManyProducts 类并解析 __construct 中的所有 BelongsToMany 变量......我想你明白了。

使 BelongsToManySpecial 类扩展原始 BelongsToMany 类并向 BelongsToManySpecial 类编写同步函数。
public function sync($ids, $detaching = true) {

// Call the parent class for default functionality
$changes = parent::sync($ids, $detaching);

// $changes = [ 'attached' => [...], 'detached' => [...], 'updated' => [...] ]
// Add your functionality
// Here you have access to everything the BelongsToMany function has access and also know what changes the sync function made.

// Return the original response
return $changes
}

或者覆盖 detachattachNew 函数以获得类似的结果。
protected function attachNew(array $records, array $current, $touch = true) {
$result = parent::attachNew($records, $current, $touch);

// Your functionality

return $result;
}

public function detach($ids = null, $touch = true)
$result = parent::detach($ids, $touch);

// Your functionality

return $result;
}

如果您想深入挖掘并了解幕后发生的事情,请分析 Illuminate\Database\Eloquent\Concerns\HasRelationship 特征 - 特别是 belongsToMany 关系函数和 BelongsToMany 类本身。

2 - 创建一个名为 BelongsToManySyncEvents 的特征,它除了返回您的特殊 BelongsToMany 类外,不会做更多的事情
trait BelongsToManySyncEvents {

public function belongsToMany($related, $table = null, $foreignKey = null, $relatedKey = null, $relation = null) {

if (is_null($relation)) {
$relation = $this->guessBelongsToManyRelation();
}

$instance = $this->newRelatedInstance($related);
$foreignKey = $foreignKey ?: $this->getForeignKey();
$relatedKey = $relatedKey ?: $instance->getForeignKey();

if (is_null($table)) {
$table = $this->joiningTable($related);
}

return new BelongsToManyWithSyncEvents(
$instance->newQuery(), $this, $table, $foreignKey, $relatedKey, $relation
);
}

}

创建 BelongsToManyWithSyncEvents 类:
class BelongsToManyWithSyncEvents extends BelongsToMany {

public function sync($ids, $detaching = true) {

$changes = parent::sync($ids, $detaching);

// Do your own magic. For example using these variables if needed:
// $this->get() - returns an array of objects given with the sync method
// $this->parent - Object they got attached to
// Maybe call some function on the parent if it exists?

return $changes;
}

}

现在将特征添加到您的类中。

3 - 结合以前的解决方案并将此功能添加到您在 BaseModel 类等中拥有的每个模型中。例如,让它们检查并调用一些方法,以防它被定义......
$functionName = 'on' . $this->foreignKey . 'Sync';

if(method_exists($this->parent), $functionName) {
$this->parent->$functionName($changes);
}

4 - 创建服务

在该服务中创建一个您必须始终调用的函数,而不是默认的 sync() 。也许称之为 attachAndDetachProducts(...) 并添加您的事件或功能

由于我没有太多关于您的类和关系的信息,您可能可以选择比我提供的更好的类名。但是,如果您现在的用例只是清除缓存,那么我认为您可以使用一些提供的解决方案。

关于php - 数据透视表的 Laravel 观察者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45103552/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com