我创建了与之关联的News
模型NewsObserver
。我希望在updated
/ updating
事件上传递给模型的旧数据和新数据做一些逻辑,但传递模型的转储与原始属性具有相同的属性,但'updated_at'
字段除外。我做错了什么?
public function updating(News $item)
{
dd($item);
}
这是附加观察者的地方
use App\Observers\NewsObserver;
use App\Observers\FileObserver;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
News::observe(NewsObserver::class);
File::observe(FileObserver::class);
}
以下是我的NewsObserver
事件updating
的一部分。 dd
的{{1}}仅包含旧数据
$item
下面提供了描述namespace App\Observers;
use App\News;
class NewsObserver
{
/**
* Listen to the News updated event.
*
* @param \App\News $item
* @return void
*/
public function updating(News $item)
{
$publish_at = request()->input('publish_at');
$item->publish_at = $publish_at ? $publish_at : $item->publish_at;
dd($item);
}
的示例。除dd
属性外,新属性和原始属性相同。但新标题应为updated_at
。当然,新数据会在数据库中正确保存,但在news NEW title
或updating
事件中,我看不到'脏'属性
update
答案 0 :(得分:5)
我想你正在寻找:
getOriginal,getAttributes,isDirty,getDirty等......
请阅读文档并使用您想要的任何内容:https://laravel.com/api/5.3/Illuminate/Database/Eloquent/Model.html#method_getOriginal
所以我会这样做:
$before = $item->toArray();
$item->title = request()->input('title', $item->title);
// some changes
if($item->save()) {
$after = $item->toArray();
$changes = array_diff_assoc($before, $after);
Logs::create(compact('before', 'after', 'changes'));
}
或那样更优雅:
public function updating(News $item) {
$changes = array();
foreach($item->getDirty() as $key => $value){
$original = $model->getOriginal($key);
$changes[$key] = [
'old' => $original,
'new' => $value,
];
}
Log::create(['model' => __CLASS__, 'changes' => serialize($changes)]);
});
或模型类中的重载save
运算符:
trait LogSave {
public function save(array $options = array()) {
$changed = $this->isDirty() ? $this->getDirty() : false;
parent::save();
if($changed) {
// log changes
}
}
}
class News extends Model {
use LogSave;
}
我也有想法:
1)如果在模型中使用old = true
标记,并且实际更新实际创建新记录并使用old
更新所有old = true
版本,那么它将很容易管理/只需更新old = false
必需的版本即可进行回滚更改。跟踪新闻ID你必须在你的表/模型中保留一些uuid
字段。
2)拥有news_revisions
并只创建旧News
($item
)对象NewsRevision
并更新当前对象。
答案 1 :(得分:0)
(代表OP发布解决方案)。
问题解决了。我没有在这里发布的一件事是前面几行使用的$item->touch()
方法。我忘了可能只在updated_at
字段上触发更新事件。我的错。谢谢你的帮助!
答案 2 :(得分:0)
另外值得注意的是,如果您有多个侦听器,您可以让以前的侦听器更改原始侦听器。
因此,如果您的 EventServiceProvider
中有以下内容:
OrderUpdatedEvent::class => [
RecreateReceiptsListener::class,
OtherListener::class, // the troublesome one
],
只需切换它们:
OrderUpdatedEvent::class => [
OtherListener::class, // the troublesome one
RecreateReceiptsListener::class,
],
现在 getOriginal()
包含原始值。