Laravel 更新 eloquent 事件:旧数据与新数据相同
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40061667/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel updating eloquent event: old data same as new
提问by piotr
I've created Newsmodel NewsObserverassociated to it. I want to do some logic with old and new data passed to model on updated/updatingevent, but dump of passed model have identical attributes as original attributes, except 'updated_at'field. What am I doing wrong?
我已经创建了与之关联的News模型NewsObserver。我想对传递给updated/updating事件模型的旧数据和新数据进行一些逻辑处理,但是传递模型的转储与原始属性具有相同的属性,'updated_at'字段除外。我究竟做错了什么?
public function updating(News $item)
{
dd($item);
}
Here is where observer is attached
这是观察者所在的位置
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);
}
And here is a part of my NewsObserverwith my updatingevent. ddof $itemcontains only old data
这是NewsObserver我的updating活动的一部分。ddof$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);
}
The example of described ddis provided below. New and original attributes are identical except updated_atproperty. But the new title should be news NEW title. Of course new data is saved properly in database, but in updatingor updateevent I don't see 'dirty' attributes
dd下面提供所描述的示例。除了updated_at属性之外,新的和原始的属性是相同的。但新标题应该是news NEW title. 当然,新数据已正确保存在数据库中,但在updating或update事件中我看不到“脏”属性
#attributes: array:13 [▼
"id" => 7
"created_at" => "2016-10-15 19:46:04"
"updated_at" => "2016-10-15 19:47:11"
"publish_at" => "2016-10-15 19:46:00"
"title" => "news OLD title"
"slug" => "news-old-title"
"content" => "<p>news OLD content</p>"
"lead" => ""
#original: array:13 [▼
"id" => 7
"created_at" => "2016-10-15 19:46:04"
"updated_at" => "2016-10-15 19:46:21"
"publish_at" => "2016-10-15 19:46:00"
"title" => "news OLD title"
"slug" => "news-old-title"
"content" => "<p>news OLD content</p>"
回答by num8er
I think You're looking for:
我认为您正在寻找:
getOriginal, getAttributes, isDirty, getDirty and so on...
getOriginal、getAttributes、isDirty、getDirty 等等...
please read docs and use whichever You want: https://laravel.com/api/5.3/Illuminate/Database/Eloquent/Model.html#method_getOriginal
请阅读文档并使用任何你想要的:https: //laravel.com/api/5.3/Illuminate/Database/Eloquent/Model.html#method_getOriginal
So I'll do that process this way:
所以我会这样做:
$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'));
}
or that way more elegant:
或者那样更优雅:
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)]);
});
or to overload saveoperator in model class with this:
或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;
}
also I've to ideas:
我也有想法:
1) what about having old = trueflag in model and when doing update actually to create new record and update all oldversion with old = truein this case it will be easy to manage/rollback changes just by updating old = falsenecessary version. to keep track of the news id You'll have to keep some uuidfield in Your table/model.
1)如何old = true在模型中设置标志以及在实际进行更新以创建新记录并更新所有old版本时如何,old = true在这种情况下,只需更新old = false必要的版本即可轻松管理/回滚更改。跟踪新闻 ID 你必须uuid在你的表/模型中保留一些字段。
2) to have news_revisionsand just to create old News($item) object to NewsRevisionand update the current one.
2) 拥有news_revisions并且只是创建旧News( $item) 对象NewsRevision并更新当前对象。
回答by halfer
(Posted solution on behalf of the OP).
(代表OP发布解决方案)。
Problem solved. The one thing I didn't post here is the $item->touch()method used few lines before. I forgot that may fire update event only on updated_atfield. My mistake. Thanks for all your help!
问题解决了。我没有在这里发布的一件事是$item->touch()之前使用了几行的方法。我忘了可能只在updated_at现场触发更新事件。我的错。感谢你的帮助!

