我有一个名为RecordsUserActivity的特性,当用户创建,更新或删除使用此特征的内容时,它基本上在活动表中创建记录。这是代码:
trait RecordsUserActivity
{
protected static function boot()
{
parent::boot();
foreach (static::getModelEvents() as $event) {
static::$event(function ($model) use ($event) {
$model->addActivity($event);
});
}
}
protected function addActivity($event)
{
$newActivity = [
'subject_id' => $this->id,
'subject_type' => get_class($this),
'action' => $event,
'user_id' => (Auth::id()) ?? null,
];
if ($event == 'updated') {
$newActivity['data'] = json_encode($this->getDirty());
}
UserActivity::create($newActivity);
}
protected static function getModelEvents()
{
if (isset(static::$recordEvents)) {
return static::$recordEvents;
}
return ['created', 'deleted', 'updated'];
}
}
然后我有另一个特性记录了使用它的模型中的属性变化。这是代码:
trait RecordsPropertyChangelog
{
protected static function boot()
{
parent::boot();
static::updated(function ($model){
$model->addPropertiesChangelog();
});
}
protected function addPropertiesChangelog()
{
$dirty = $this->getDirty();
foreach ($dirty as $field => $newData) {
$oldData = $this->getOriginal($field);
$this->addPropertyChangelog($field,$oldData,$newData);
}
}
protected function addPropertyChangelog($fieldName,$oldValue,$newValue)
{
PropertyChangelog::create([
'resource_id' => $this->id,
'resource_type' => get_class($this),
'property' => $fieldName,
'from_value' => $oldValue,
'to_value' => $newValue,
'data' => '{}',
]);
}
}
当我在模型中包含两个特征并进行更新时,会出现问题,两个更新的模型事件都会发生某种冲突。有没有办法解决这个问题,还是应该找到另一种解决方案?
答案 0 :(得分:3)
如果您尝试在同一型号上同时使用这两种特性,应该收到错误,说明Trait method boot has not been applied, because there are collisions with other trait methods...
。
无论如何,您不希望自己的特征定义boot()
方法。如果你有一个需要挂钩Model
方法的特征,Laravel的boot
有一个特殊的约定。基本上,在您的特征中,以boot{traitName}
的格式定义方法。另外,在两种方法中删除对parent::boot()
的调用。基础boot()
上的Model
方法将在Model
启动时调用符合此格式的方法。
所以,你的特质应该是这样的:
trait RecordsUserActivity
{
protected static function bootRecordsUserActivity()
{
foreach (static::getModelEvents() as $event) {
static::$event(function ($model) use ($event) {
$model->addActivity($event);
});
}
}
//...
}
trait RecordsPropertyChangelog
{
protected static function bootRecordsPropertyChangelog()
{
static::updated(function ($model) {
$model->addPropertiesChangelog();
});
}
//...
}
答案 1 :(得分:1)
根据laravel文档,您应该使用Laravel Model Observers来管理模型事件:
<?php
namespace App\Observers;
use App\User;
class UserObserver
{
/**
* Listen to the User created event.
*
* @param User $user
* @return void
*/
public function created(User $user)
{
//
}
/**
* Listen to the User deleting event.
*
* @param User $user
* @return void
*/
public function deleting(User $user)
{
//
}
}
要注册观察者,请在要观察的模型上使用observe方法。您可以在其中一个服务提供商的引导方法中注册观察者。在这个例子中,我们将在AppServiceProvider中注册观察者:
<?php
namespace App\Providers;
use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}
希望这有帮助!