Laravel Eloquent在做出更改的情况下进行更新


Laravel Eloquent update just if changes have been made

如果对Laravel中的记录进行了更改,是否有任何方法可以使用雄辩的模型更新该记录?我不希望任何用户无正当理由一次又一次地请求数据库,只需点击按钮即可保存更改。我有一个javascript功能,可以根据页面中是否发生了更改来启用和禁用保存按钮,但我想知道是否可以确保在服务器端也执行这种功能。我知道我可以自己完成(意思是:不需要求助于框架的内部功能),只需检查记录是否发生了变化,但在这样做之前,我想知道Laravel雄辩的模型是否已经解决了这一问题,所以我不需要重新发明轮子。

这是我用来更新记录的方式:

$product = Product::find($data["id"]);
$product->title = $data["title"];
$product->description = $data["description"];
$product->price = $data["price"];
//etc (string values were previously sanitized for xss attacks)
$product->save();

您已经在做了!

save()将检查模型中的某些内容是否发生了更改。如果没有,它就不会运行数据库查询。

以下是Illuminate'Database'Eloquent'Model@performUpdate:中代码的相关部分

protected function performUpdate(Builder $query, array $options = [])
{
    $dirty = $this->getDirty();
    if (count($dirty) > 0)
    {
        // runs update query
    }
    return true;
}

getDirty()方法只是将当前属性与创建模型时保存在original中的副本进行比较。这是在syncOriginal()方法中完成的:

public function __construct(array $attributes = array())
{
    $this->bootIfNotBooted();
    $this->syncOriginal();
    $this->fill($attributes);
}
public function syncOriginal()
{
    $this->original = $this->attributes;
    return $this;
}

如果你想检查模型是否脏,只需调用isDirty():

if($product->isDirty()){
    // changes have been made
}

或者,如果你想检查某个属性:

if($product->isDirty('price')){
    // price has changed
}

即使在持久化之后,也可以在Eloquent模型上使用$product->getChanges()。查看此处的文档

我喜欢添加这个方法,如果你使用的是编辑表单,你可以使用这个代码来保存update(Request $request, $id)函数中的更改:

$post = Post::find($id);    
$post->fill($request->input())->save();

请记住,您必须使用相同的列名来命名输入。fill()函数将为您完成所有工作:)

有时您需要将新更改的值与上一个值进行比较,如果您正在寻找,这里是解决方案。

if (
    $obj->isDirty('some_field_name') &&
    $obj->some_field_name != $obj->getOriginal('some_field_name')
) {
    // Make required changes...
}
    });
}

导出的解决方案的参考文献在这里。

仅使用以下内容:

Product::where('id', $id)->update($request->except(['_token', '_method']));

也许Laravel已经更新了,但在之前的所有答案中,wasChangedisDirty更适合我。

例如:

if($post->wasChanged('status') && $post->status == 'Ready') // Do thing