Czy istnieje sposób, aby zaktualizować rekord w Laravel przy użyciu elokwentnych modeli, tylko jeśli wprowadzono zmianę w tym rekordzie? Nie chcę, aby jakikolwiek użytkownik żądał bazy danych bez dobrego powodu w kółko, po prostu naciskając przycisk, aby zapisać zmiany. Mam javascript
funkcję, która włącza i wyłącza przycisk zapisywania w zależności od tego, czy coś się zmieniło na stronie, ale chciałbym wiedzieć, czy jest możliwe, aby zrobić tego rodzaju funkcję również po stronie serwera. Wiem, że mogę to zrobić sam (czyli: bez odwoływania się do wewnętrznej funkcjonalności frameworka) po prostu sprawdzając, czy rekord się zmienił, ale zanim to zrobię, chciałbym wiedzieć, czy elokwentny model Laravela już dba o to to, więc nie muszę ponownie wymyślać koła.
Oto sposób, w jaki aktualizuję rekord:
$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();
dirty
flagę, która jest używana do określenia, czy aktualizacja bazy danych jest rzeczywiście wymagana, a ta flaga jest ustawiana przez porównanie oryginalnychfind
wartości kolumn z wartościami w punkcie, w którym wykonujesz zapisOdpowiedzi:
Już to robisz!
save()
sprawdzi czy coś w modelu się zmieniło. Jeśli tak nie jest, nie uruchomi zapytania db.Oto odpowiednia część kodu w
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()
Metoda po prostu porównuje bieżące atrybuty z kopii zapisanej woriginal
kiedy model jest tworzony. Odbywa się tosyncOriginal()
metodą:public function __construct(array $attributes = array()) { $this->bootIfNotBooted(); $this->syncOriginal(); $this->fill($attributes); } public function syncOriginal() { $this->original = $this->attributes; return $this; }
Jeśli chcesz sprawdzić czy model nie jest zabrudzony to zadzwoń
isDirty()
:if($product->isDirty()){ // changes have been made }
Lub jeśli chcesz sprawdzić określony atrybut:
if($product->isDirty('price')){ // price has changed }
źródło
isDirty()
do tego użyć . Zobacz zaktualizowaną odpowiedźisDirty()
.getChanges()
metoda. Sprawdź moją odpowiedź stackoverflow.com/a/54132163/1090395isDirty()
będzie,true
jeśli nie rzucisz dobrze swoich atrybutów. Miałem float, który był dokładnie taki sam jak w bazie danych, jednak ponieważ ustawiałem float za pomocą łańcucha (na przykład „10,50” zamiast 10,50), wykryłby to jako zmianę i wykonał aktualizację.Możesz używać
getChanges()
na modelu Eloquent nawet po wytrwałości.źródło
Lubię dodawać tę metodę, jeśli korzystasz z formularza edycji, możesz użyć tego kodu, aby zapisać zmiany w swojej
update(Request $request, $id)
funkcji:pamiętaj, że musisz nazwać swoje dane wejściowe taką samą nazwą kolumny.
fill()
Funkcja wykona całą pracę za Ciebie :)źródło
fill
i jak masowo przekazać do niej żądanie. Dzięki! Nie musiałem jednak podawać identyfikatora, ponieważ jestem aktualizowany, więc już tam jest$request->id
.