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

时间:2016-10-15 16:44:48

标签: laravel observers

我创建了与之关联的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 titleupdating事件中,我看不到'脏'属性

update

3 个答案:

答案 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() 包含原始值。