我对任何模型都有观察者特征MainObserver
。
<?
namespace App\Observers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Models\AppEvent;
use App\Models\AppEventData;
trait MainObserver
{
public function handleCreatedEvent($model) {
$event = new AppEvent;
$event->event_type = 'CREATE';
$event->model_type = $model::getModelType();
$event->model_id = $model->id;
$event->creator_id = Auth::user() ? Auth::user()->id : null;
$event->save();
}
public function handleUpdatedEvent($model) {
$originalData = $model->getOriginal();
$newData = $model->getAttributes();
$modelType = $model::getModelType();
$modelFields = $model->getFieldsKeys();
$event = new AppEvent;
$event->event_type = 'EDIT';
$event->model_type = $modelType;
$event->model_id = $model->id;
$event->creator_id = Auth::user() ? Auth::user()->id : null;
$eventDataArray = [];
foreach($modelFields as $modelAttribute) {
if(!$model->shouldSaveEventForField($modelAttribute)) continue;
if(!isset($originalData[$modelAttribute])) {
$originalData[$modelAttribute] = null;
}
if(!isset($newData[$modelAttribute])) {
$newData[$modelAttribute] = null;
}
if($originalData[$modelAttribute] !== $newData[$modelAttribute]) {
$eventData = new AppEventData;
$eventData->field = $modelAttribute;
$fieldData = $model->getField($modelAttribute);
if($fieldData['type'] === 'password') {
$originalData[$modelAttribute] = '***';
$newData[$modelAttribute] = '******';
}
$eventData->old_value = $originalData[$modelAttribute];
$eventData->new_value = $newData[$modelAttribute];
$eventDataArray[] = $eventData;
}
}
if(!count($eventDataArray)) return;
DB::transaction(function() use($event, $eventDataArray) {
$event->save();
$event->eventData()->saveMany($eventDataArray);
});
}
}
它就像这样使用
<?
namespace App\Observers;
use App\Models\User;
class UserObserver
{
use MainObserver;
public function created(User $user) {
$this->handleCreatedEvent($user);
}
public function updated(User $user) {
$this->handleUpdatedEvent($user);
}
}
namespace App\Observers;
use App\Models\User;
class UserObserver
{
use MainObserver;
public function created(User $user) {
$this->handleCreatedEvent($user);
}
public function updated(User $user) {
$this->handleUpdatedEvent($user);
}
// in AppServiceProvider
User::observe(UserObserver::class);
问题是:它不存储外来关系(belongsToMany)。
所以我为我的模特写了这个特性
public function setAttribute($key, $value) {
$pivot = static::getFieldPivotField($key);
if( $pivot ) {
$this->delayedSave[] = [
'key' => $key, 'value' => $value, 'pivot' => $pivot
];
return;
}
return parent::setAttribute($key, $value)
}
public function save(array $options = array()) {
$exists = $this->exists;
$dirty = $this->getDirty();
$saved = parent::save($options);
if($saved) {
foreach($this->delayedSave as $v) {
$this->savePivot($v['key'], $v['value'], $v['pivot']);
}
$this->delayedSave = [];
}
}
最后,savePivot
:它需要旧的ids
和新的ids
来支持枢轴并存储它们,如果发生了变化。
private function savePivot($key, $value, $pivot) {
$ids = array_column($value, 'id');
$old = $this->{$key}()->get()->pluck('pivot.' . $pivot)->toArray();
if($old === $ids) return;
$event = new AppEvent;
$event->event_type = 'EDIT';
$event->model_type = $this::getModelType();
$event->model_id = $this->id;
$event->creator_id = Auth::user() ? Auth::user()->id : null;
$eventDataArray = [];
$eventData = new AppEventData;
$eventData->field = $key;
$eventData->old_value = join('|', $old);
$eventData->new_value = join('|', $ids);
$eventDataArray[] = $eventData;
DB::transaction(function() use($event, $eventDataArray, $key, $ids) {
$this->{$key}()->sync($ids);
$event->save();
$event->eventData()->saveMany($eventDataArray);
});
}
可能是太多了,有一种简单的方法来存储外交关系更新的日志?