Laravel更新雄辩事件:旧数据与新数据相同

pio*_*otr 0 observers laravel

我创建了与之相关的News模型NewsObserver.我想对传递给updated/ on updating事件的模型传递新旧数据做一些逻辑,但传递模型的转储与原始属性具有相同的属性,除了'updated_at' 字段.我究竟做错了什么?

public function updating(News $item)
{
    dd($item);
}
Run Code Online (Sandbox Code Playgroud)

这是观察者所附的地方

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);
}
Run Code Online (Sandbox Code Playgroud)

这是我NewsObserver参加updating活动的一部分.dd$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);
}
Run Code Online (Sandbox Code Playgroud)

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>"
Run Code Online (Sandbox Code Playgroud)

num*_*8er 6

我想你正在寻找:

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'));
}
Run Code Online (Sandbox Code Playgroud)

或那样更优雅:

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)]);
});
Run Code Online (Sandbox Code Playgroud)

或者使用以下方法重载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;
}
Run Code Online (Sandbox Code Playgroud)

我也有想法:

1)如果old = true在模型中有标志并且实际更新时创建新记录并更新所有old版本,old = true在这种情况下,只需更新old = false必要的版本就可以轻松管理/回滚更改.跟踪新闻ID你必须uuid在你的表/模型中保留一些字段.

2)拥有news_revisions并只是创建old News($item)对象NewsRevision并更新当前的对象.