laravel Laravel4 - 跟踪 Eloquent 保存的更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21266030/
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
Laravel4 - Track changes to be saved by Eloquent
提问by Nerva
In Laravel 4, I have a class extending Eloquent and I need to record changes (to keep the history) at the time of saving.
在 Laravel 4 中,我有一个扩展 Eloquent 的类,我需要在保存时记录更改(以保留历史记录)。
Saving event in boot function is called as expected. The question is: how do I know which fields were changed and are about to be saved? Also, can I access existing values without loading the record again?
启动函数中的保存事件按预期调用。问题是:我如何知道哪些字段已更改并且将要保存?另外,我可以在不再次加载记录的情况下访问现有值吗?
I know, one way could be to load the record again and compare all fields one by one. Is there any better optimized way to do that?
我知道,一种方法可能是再次加载记录并一一比较所有字段。有没有更好的优化方法来做到这一点?
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;
}
);
}
}
Thank you.
谢谢你。
回答by Nerva
Eloquent's getDirty()
and getOriginal()
did the trick:
EloquentgetDirty()
并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;
}
);
回答by serdar.sanri
I don't think accepted answer is the best way to do that. Why would you loop through all changed fields to figure out what has changed? Laravel has this two Model methods that can help you better,
我不认为接受的答案是最好的方法。为什么要遍历所有更改的字段以找出更改的内容?Laravel 有这两个 Model 方法可以更好的帮助你,
on save function/route/controller whichever you use
在保存功能/路由/控制器上,无论您使用哪个
$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
....
}
}
回答by Antonio Carlos Ribeiro
You can use events:
您可以使用事件:
Event::listen('saving', function($model)
{
// Do whatever you need to do with your $model before saving or not:
return true;
});
You can also hook that saving method to any controller action:
您还可以将该保存方法挂钩到任何控制器操作:
Event::listen('saving', 'LogThings@saving');
回答by HymanPoint
I have something like this in my project.
我的项目中有这样的事情。
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')));
}
}
}
});
回答by whycodewhyyyy
The Eloquent class that you're extending has getOriginal()
and getAttributes()
methods to get the originally-hydrated properties and the currently set properties, respectively.
您正在扩展的 Eloquent 类具有getOriginal()
和getAttributes()
方法,分别用于获取原始水合属性和当前设置的属性。
So, in your saving event you can do something like...
因此,在您的保存事件中,您可以执行以下操作...
if ( ! empty( array_diff( $record->getOriginal(), $record->getAttributes() ) ) )
{
//log changes
}
If you want to do this for all/most of your Models, I suggest abstracting this out to a generic 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);