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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 14:37:09  来源:igfitidea点击:

Laravel updating eloquent event: old data same as new

laravelobservers

提问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. 当然,新数据已正确保存在数据库中,但在updatingupdate事件中我看不到“脏”属性

#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现场触发更新事件。我的错。感谢你的帮助!