Cập nhật Laravel Eloquent chỉ khi các thay đổi đã được thực hiện


86

Có cách nào để cập nhật bản ghi trong Laravel bằng cách sử dụng các mô hình hùng hồn chỉ khi một thay đổi đã được thực hiện đối với bản ghi đó? Tôi không muốn bất kỳ người dùng nào yêu cầu cơ sở dữ liệu mà không có lý do chính đáng, chỉ cần nhấn nút để lưu các thay đổi. Tôi có một javascriptchức năng bật và tắt nút lưu tùy theo việc có điều gì đó đã thay đổi trong trang hay không, nhưng tôi muốn biết liệu có thể đảm bảo thực hiện loại tính năng này ở phía máy chủ hay không. Tôi biết tôi có thể tự mình hoàn thành nó (nghĩa là: mà không cần đến chức năng bên trong của khung) chỉ bằng cách kiểm tra xem bản ghi có thay đổi hay không, nhưng trước khi làm theo cách đó, tôi muốn biết liệu mô hình hùng hồn Laravel đã xử lý điều đó, vì vậy tôi không cần phải phát minh lại bánh xe.

Đây là cách tôi sử dụng để cập nhật bản ghi:

$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
Tại sao không cho phép cơ sở dữ liệu khai thác gỗ và sau đó kiểm tra các bản ghi để xem những gì truy vấn hùng biện thực sự thực hiện khi bạn làm một tiết kiệm: bạn có thể ngạc nhiên ngạc
Mark Baker

4
Lưu ý rằng các mô hình Laravel giữ một dirtylá cờ được sử dụng để xác định xem một bản cập nhật trên cơ sở dữ liệu là thực sự cần thiết, và lá cờ này được thiết lập bằng cách so sánh ban đầu findgiá trị cột với các giá trị tại các điểm mà bạn thực hiện tiết kiệm
Mark Baker

@MarkBaker Đó là một mẹo hay!
user2755140

Câu trả lời:


177

Bạn đã làm điều đó!

save()sẽ kiểm tra xem một cái gì đó trong mô hình đã thay đổi. Nếu không, nó sẽ không chạy một truy vấn db.

Đây là phần có liên quan của mã trong Illuminate\Database\Eloquent\Model@performUpdate:

protected function performUpdate(Builder $query, array $options = [])
{
    $dirty = $this->getDirty();

    if (count($dirty) > 0)
    {
        // runs update query
    }

    return true;
}

Các getDirty()phương pháp đơn giản là so sánh các thuộc tính hiện tại với một bản sao lưu trong originalkhi mô hình được tạo ra. Điều này được thực hiện trong syncOriginal()phương pháp:

public function __construct(array $attributes = array())
{
    $this->bootIfNotBooted();

    $this->syncOriginal();

    $this->fill($attributes);
}

public function syncOriginal()
{
    $this->original = $this->attributes;

    return $this;
}

Nếu bạn muốn kiểm tra xem mô hình có bị bẩn hay không, chỉ cần gọi isDirty():

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

Hoặc nếu bạn muốn kiểm tra một thuộc tính nhất định:

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

Thật tuyệt. Cảm ơn bạn. Tôi tự hỏi bây giờ làm thế nào tôi có thể truy cập vào cờ bẩn đó để biết nếu một nỗ lực cập nhật đã được thực hiện mà không thực hiện bất kỳ thay đổi nào? Ý tôi là: lợi nhuận cho hành động đó?
user2755140

1
@DaseinA Bạn có thể sử dụng isDirty()cho điều đó. Xem câu trả lời được cập nhật
lukasgeiter

2
Đối với những người đọc này, hãy chắc chắn kiểm tra câu trả lời này trước khi sử dụng isDirty().
Alex

1
getChanges()phương pháp. Kiểm tra câu trả lời của tôi stackoverflow.com/a/54132163/1090395
Mladen Janjetovic

FYI isDirty()sẽ là truenếu bạn không thực hiện đúng các thuộc tính của mình. Tôi đã có một float giống hệt như trong cơ sở dữ liệu, tuy nhiên, vì tôi đang đặt float bằng một chuỗi (ví dụ "10.50" thay vì 10.50), nó sẽ phát hiện nó là một thay đổi và thực hiện cập nhật.
Maarten de Graaf


11

Tôi muốn thêm phương pháp này, nếu bạn đang sử dụng biểu mẫu chỉnh sửa, bạn có thể sử dụng mã này để lưu các thay đổi trong update(Request $request, $id)hàm của mình :

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

hãy nhớ rằng bạn phải đặt tên đầu vào của mình với cùng tên cột. Các fill()chức năng sẽ làm tất cả công việc cho bạn :)


3
Đây thực sự là câu trả lời mà tôi đang tìm kiếm, tôi quên mất tên fillvà cách chuyển hàng loạt yêu cầu đến nó. Cảm ơn! Tôi không cần phải chuyển ID mặc dù, vì tôi đang cập nhật, vì vậy nó đã ở đó $request->id.
blamb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.