我目前正在使用Laravel应用程序,该应用程序使用Model事件在数据库中执行数据验证/同步。
我有一张包含重要数据的表格。此表针对不同的模型更新进行了更新。我使用模型事件来处理它。它适用于模型属性示例:
<?php
Product::saved(function (Product $p) {
$dirty = collect($p->getDirty());
if ($dirty->has('ugr') || $dirty->has('ra')) {
//Do some stuff here
}
});
凭借这种逻辑,我可以限制我的东西&#34;在特定模型属性更新上执行。
如何对Product
关系进行此类检查?
我可以通过applications
上的Product
方法访问ManyToMany关系,如何知道链接的应用程序列表自模型加载后是否已更改?
感谢您的帮助!
答案 0 :(得分:3)
我还没有找到一种方法直接与Laravel一起做这件事。我已经使用Application事件和Relation继承构建了一个解决方案。
我添加了名为trait
的{{1}},其目标是通知关系更新:
App\Database\Eloquent\FollowUpdatedRelations
我在模型中使用了这个特性,我需要遵循关系更新,并且我已经更新了关系定义:
<?php
namespace App\Database\Eloquent;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use App\Library\Decorator;
use App\Events\RelationUpdated;
trait FollowUpdatedRelations
{
/**
* The default error bag.
*
* @var string
*/
protected $updatedRelations = [];
/**
* Check if the belongs to many relation has been updated
* @param BelongsToMany $relation
* @param array $syncResult Result of the `sync` method call
* @return boolean
*/
protected function hasBeenUpdated(BelongsToMany $relation, array $syncResult)
{
if (isset($syncResult['attached']) && count($syncResult['attached']) > 0) {
$this->updatedRelations[$relation->getRelationName()] = true;
event(new RelationUpdated($relation));
} elseif (isset($syncResult['detached']) && count($syncResult['detached']) > 0) {
$this->updatedRelations[$relation->getRelationName()] = true;
event(new RelationUpdated($relation));
}
}
/**
* Decorate a BelongsToMany to listen to relation update
* @param BelongsToMany $relation
* @return Decorator
*/
protected function decorateBelongsToMany(BelongsToMany $relation)
{
$decorator = new Decorator($relation);
$decorator->decorate('sync', function ($decorated, $arguments) {
$updates = call_user_func_array([$decorated, 'sync'], $arguments);
$this->hasBeenUpdated($decorated, $updates);
return $updates;
});
return $decorator;
}
/**
* Retrieve the list of dirty relations
* @return array
*/
public function getDirtyRelations()
{
return $this->updatedRelations;
}
}
<?php
...
class Product extends Model
{
use FollowUpdatedRelations;
....
/**
* Defines relationship with App\Applications model
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function applications()
{
return $this->decorateBelongsToMany(
$this->belongsToMany('App\Application', 'product_application')
);
}
}
类包装一个对象并添加覆盖方法的能力:
App\Library\Decorator
使用该对象,我可以在<?php
namespace App\Library;
use Closure;
class Decorator
{
/**
* Decorated instance
* @var mixed
*/
private $decorated;
private $methods = [];
/**
* Decorate given instance
* @param mixed $toDecorate
*/
public function __construct($toDecorate)
{
$this->decorated = $toDecorate;
}
/**
* Decorate a method
* @param string $name
* @param Closure $callback Method to run instead of decorated one
*/
public function decorate($name, Closure $callback)
{
$this->methods[$name] = $callback;
return $this;
}
/**
* Call a method on decorated instance
* @param string $name
* @param array $arguments
* @return mixed
*/
public function __call($name, $arguments)
{
if (isset($this->methods[$name])) {
return call_user_func_array($this->methods[$name], [$this->decorated, $arguments]);
}
return call_user_func_array([$this->decorated, $name], $arguments);
}
}
Laravel关系上创建自定义sync
方法。我使用sync方法来跟踪更新,因为它返回数据透视表中附加,分离和更新模型的列表。
我只需要计算是否有附加或分离的模型并调度相应的事件。我的活动是BelongsToMany
,其中包含已更新的关系作为属性。
然后我可以在App\Events\RelationUpdated
中添加一个事件监听器:
EventServiceProvider
我可以放置关系更新时必须执行的所有内容。看起来有点复杂,但我认为依赖于这样的东西比在每个模型构造上添加逻辑要轻。
希望这有帮助!
答案 1 :(得分:1)
没有现成的方法来做到这一点。实际上,您希望在更新子对象时通知父对象。换句话说,如果更新了任何相关的应用程序,您希望在Product上触发已保存的处理程序。
如果我的理解是正确的,那么你需要通过Product模型注册处理程序,因为如果你只想通知它相关的子模型更新的相关模型,那么你可以简单地使用 AWS.config.update({
accessKeyId: $rootScope.s3.akey,
secretAccessKey: $rootScope.s3.skey
});
s3=new AWS.S3({apiVersion: '2006-03-01'});
s3.listObjects({Bucket:$rootScope.s3.bucket}, function(err,data){
if(err) console.log(err);
else console.log(data);
})
属性如果更改了任何子模型,则子模型将始终更新父模型。
因为,您希望仅跟踪更改主要加载时(急切地)加载的相关模型,因此您需要通过父/主模型本身在相关模型上注册已保存的处理程序。如果我仍然在正确的轨道上,你可以尝试这样的事情:
protected $touches
希望,你想要像我上面描述的那样。顺便说一句,这只是一个想法,您可以使用单独的类/方法在子模型上注册事件处理程序,以保持代码清洁。