Проверка Laravel при обновлении updateOrCreate
В моем контроллере есть следующий код:
for($i=0; $i<$number_of_tourists; $i++) {
$tourist = Tourist::updateOrCreate(['doc_number' => $request['doc_number'][$i]],
$tourist_to_update);
}
каждый раз, когда "updateOrCreate" работает, он делает 1 из 3 вещей:
1) обновляет модель instanse ИЛИ
2) создает и сохраняет новый OR
3) оставляет все неизменным (если модель с такими значениями уже существует).
Мне нужно проверить, выполнено ли "updateOrCreate" ровно 1 (обновлено), а затем выполнить некоторый код.
Как мне это сделать?
Заранее спасибо!
Ответы
Ответ 1
В Laravel 5.5 вы можете наконец проверить, действительно ли обновления выполнялись с wasChanged
метода wasChanged
$tourist = Tourist::updateOrCreate([...]);
// If true then created otherwise maybe updated
$wasCreated = $tourist->wasRecentlyCreated;
// If true then the row in the database has been modified,
// otherwise either created or not updated
$wasChanged = $tourist->wasChanged();
if(!$wasCreated && $wasChanged){
// user existed and there were actually updates taking place.
}
if($wasCreated && !$wasChanged){
// user was created. The row wasn't updated after creation.
}
// If true then the object '$tourist' has been modified but not saved
$tourist->isDirty();
//You can also check if a specific attribute was changed:
$tourist->wasChanged('name');
$tourist->isDirty('name');
Ответ 2
Достаточно легко определить, вызвала ли функция обновление или вставку (проверьте свойство wasRecentlyCreated
). Однако при использовании этой функции легче определить, действительно ли произошло обновление (если модель существует, но не загрязнена, обновление не будет выполнено). Я бы посоветовал не использовать эту функцию и самостоятельно расщепить функциональность.
Это определение функции:
public function updateOrCreate(array $attributes, array $values = [])
{
$instance = $this->firstOrNew($attributes);
$instance->fill($values)->save();
return $instance;
}
Чтобы интегрировать это в ваш код, я бы предложил что-то вроде:
for ($i=0; $i<$number_of_tourists; $i++) {
$tourist = Tourist::firstOrNew(['doc_number' => $request['doc_number'][$i]]);
$tourist->fill($tourist_to_update);
// if the record exists and the fill changed data, update will be performed
$updated = $tourist->exists && $tourist->isDirty();
// save the tourist (insert or update)
$tourist->save();
if ($updated) {
// extra code
}
}
Ответ 3
@patricus ниже представил рабочий путь для решения проблемы. хотя @TheFallen здесь дал решение, которое использует Eloquent Events и кажется более элегантным: Laravel Eloquent Events - реализовать, чтобы сохранить модель, если обновлено
Ответ 4
Если вы хотите всегда выполнять определенный код при обновлении строки, я бы рекомендовал создать наблюдателя для прослушивания updated
или create
вызовов.
<?php
namespace App\Observers;
use App\Tourist;
class TouristObserver
{
/**
* Listen to the User created event.
*
* @param \App\User $user
* @return void
*/
public function created(Tourist $user)
{
// this will always trigger when you created a new entry
}
/**
* Listen to the User deleting event.
*
* @param \App\Tourist $user
* @return void
*/
public function updated(Tourist $user)
{
// this will always trigger when actually a row was updated
}
}
Все, что вам нужно сделать, это зарегистрировать наблюдателя в AppServiceProvider
следующим образом:
public function boot()
{
Tourist::observe(\App\Observer\TouristObserver::class);
}