Laravel4 - 跟踪由Eloquent保存的更改

时间:2014-01-21 18:16:34

标签: php laravel laravel-4 eloquent

在Laravel 4中,我有一个扩展Eloquent的类,我需要在保存时记录更改(保留历史记录)。

按预期调用在启动函数中保存事件。问题是:我如何知道哪些字段已更改并即将保存?另外,我可以在不重新加载记录的情况下访问现有值吗?

我知道,一种方法是再次加载记录并逐个比较所有字段。有没有更好的方法来做到这一点?

class Record extends Eloquent {
  protected static function boot()
  {
    parent::boot();
    static::saving(
      function($record)
      {
        // It runs properly. This is where changes should be compared
        return true;
      }
    );
  }
}

谢谢。

5 个答案:

答案 0 :(得分:9)

Eloquent的getDirty()getOriginal()做了诀窍:

static::saving(
  function($record)
  {
    $dirty = $record->getDirty();
    foreach ($dirty as $field => $newdata)
    {
      $olddata = $record->getOriginal($field);
      if ($olddata != $newdata)
      {
        // save changes from $olddata to $newdata
      }
    }
    return true;
  }
);

答案 1 :(得分:2)

我不认为接受的答案是最好的方法。为什么要遍历所有更改的字段以找出已更改的内容? Laravel有两种模型方法可以帮助你更好,

在保存功能/路线/控制器上,无论你使用哪个

$model::find(X);
...
'''
$model->fill(Input::all());
if( !empty($model->getDirty() )
// Get status of model. if nothing has changed there is no need to get in here
{
    if($model->isDirty(  { mixed data (array,string,null) } ))
     // isDirty() will help you to find out if the field is different than original 
    {
         .....
         enter code here
         ....
    }
}

答案 2 :(得分:0)

您可以使用活动:

Event::listen('saving', function($model)
{
    // Do whatever you need to do with your $model before saving or not:

    return true;
});

您还可以将该保存方法挂钩到任何控制器操作:

Event::listen('saving', 'LogThings@saving');

答案 3 :(得分:0)

我的项目中有类似的东西。

Record::updating(function($record){
    $original = $record->getOriginal();

    foreach($original as $index => $value){
        if($index != 'updated_at' AND $index != 'created_at'){
            if($value != $record[$index]){
                RecordUpdate::create(array('record_id' => $record->id, 'fieldname' => $index, 'old_value' => $value, 'new_value' => $record[$index], 'created_at' => date('Y-m-d H:i:s')));
            }
        }
    }
});

答案 4 :(得分:0)

您正在扩展的Eloquent类具有getOriginal()getAttributes()方法,分别获取原始水合属性和当前设置的属性。

因此,在您的保存活动中,您可以执行类似......

的操作
if ( ! empty( array_diff( $record->getOriginal(), $record->getAttributes() ) ) )
{
    //log changes
}

如果您想对所有/大多数模型执行此操作,我建议将其抽象为通用Model Observer

////
/* Subclassable, generic Model Observer */
////

class ModelObserver {

    public function saving($model)
    {
        if ( ! empty( array_diff( $record->getOriginal(), $record->getAttributes() ) ) )
        {
            //log changes
        }
    }
}


////
/* Set up observers, for example in start/global.php */
////

$modelObserver = new ModelObserver;
Comment::observe($modelObserver);
Post::observe($modelObserver);
User::observe($modelObserver);