【问题标题】:Laravel Eloquent update just if changes have been madeLaravel Eloquent 更新,如果已经进行了更改
【发布时间】:2015-05-06 03:39:18
【问题描述】:

是否有任何方法可以使用 eloquent 模型更新 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();

【问题讨论】:

  • 为什么不启用数据库日志记录,然后检查日志以查看 Eloquent 在保存时实际执行的查询:您可能会感到惊喜
  • 请注意,Laravel 模型包含一个 dirty 标志,用于确定是否实际需要对数据库进行更新,并且该标志是通过将原始 find 列值与位于执行保存的点

标签: php laravel eloquent


【解决方案1】:

你已经在做!

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
}

【讨论】:

  • 太好了。谢谢你。我现在想知道如何访问该脏标志以了解是否在不进行任何更改的情况下进行了更新尝试?我的意思是:那个动作的回报?
  • 阅读本文的人,请务必在使用isDirty()之前查看this answer
  • getChanges() 方法。检查我的答案stackoverflow.com/a/54132163/1090395
  • 仅供参考,如果您没有正确转换属性,isDirty() 将是 true。我有一个与数据库中完全相同的浮点数,但是因为我使用字符串设置浮点数(例如“10.50”而不是 10.50),它会将其检测为更改并执行更新。
【解决方案2】:

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

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

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

【讨论】:

  • 这实际上是我正在寻找的答案,我忘记了fill 的名称,以及如何将请求大量传递给它。谢谢!我不需要传递 ID,因为我正在更新,所以它已经存在 $request->id
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 2015-08-30
    • 2014-07-19
    • 2017-05-10
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多