変更が加えられた場合のLaravelEloquentアップデート


87

レコードに変更が加えられた場合に、雄弁なモデルを使用して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();

3
データベースロギングを有効にしてからログをチェックして、保存時にEloquentが実際に実行するクエリを確認してください。驚くかもしれません
Mark Ba​​ker

4
Laravelモデルdirtyは、データベースの更新が実際に必要かどうかを判断するために使用されるフラグを保持していることに注意してください。このフラグは、元のfind列の値を保存を実行した時点の値と比較することによって設定されます
Mark Ba​​ker

@MarkBakerそれは素晴らしいヒントです!
user2755140 2015年

回答:


180

あなたはすでにそれをやっています!

save()モデル内の何かが変更されたかどうかを確認します。そうでない場合は、dbクエリを実行しません。

コードの関連部分は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
}

それは素晴らしいことです。ありがとうございました。変更を加えずに更新が試行されたかどうかを知るために、そのダーティフラグにアクセスするにはどうすればよいでしょうか。つまり、その行動の見返り?
user2755140 2015年

1
@DaseinAあなたはそのために使うことができますisDirty()。更新された回答を参照してください
lukasgeiter 2015年

2
これを読んでいる人は、を使用する前に必ずこの回答を確認してくださいisDirty()
アレックス

1
getChanges()方法があります。私の答えのチェックstackoverflow.com/a/54132163/1090395
ムラデンJanjetovic

参考isDirty()までにtrue、属性を正​​しくキャストしないと、そうなります。データベースとまったく同じfloatがありましたが、floatを文字列(10.50ではなく「10.50」の例)で設定していたため、変更として検出され、更新が実行されました。
マーテンデグラーフ


11

このメソッドを追加したいのですが、編集フォームを使用している場合は、次のコードを使用してupdate(Request $request, $id)関数の変更を保存できます。

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

入力には同じ列名を付ける必要があることに注意してください。fill()機能はあなたのためにすべての作業を行います:)


3
これは実際に私が探していた答えです、私は名前を忘れましたfill、そしてそれにリクエストを大量に渡す方法。ありがとう!私は更新しているので、IDを渡す必要はありませんでしたので、すでにそこにあり$request->idます。
blamb 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.