Laravel Eloquent Events - внедрить, чтобы сохранить модель, если обновлено
У меня есть такой код в контроллере:
for($i=0; $i<$number_of_tourists; $i++) {
$tourist = Tourist::updateOrCreate(['doc_number' => $request['doc_number'][$i]],
$tourist_to_update);
}
Итак, метод updateOrCreate может 1) обновить запись, 2) создать новую 3) оставить запись без изменений, если $tourist_to_update равно тому, что уже находится в БД.
Я хочу сохранять $tourist_to_update в $array[] только при обновлении записи в таблице 'tourist' (а не при создании новой записи или при отсутствии изменений).
Как я знаю, есть события Eloquent https://laravel.com/docs/5.4/eloquent, которые имеют обновления и обновления событий, которые, кажется, соответствуют моим потребностям.
Проблема в том, что я смотрел и читал несколько уроков и до сих пор не понимаю, как их использовать.
Я знаю, как зарегистрировать событие Eloquent в модели Tourist:
protected static function boot()
{
parent::boot();
static::updating(function ($model) {
});
}
Может кто-нибудь объяснить, как я могу достичь своей цели с помощью событий Eloquent?
Заранее спасибо.
3 ответа
Это немного более сложный подход, но если вы хотите получать только обновленные записи, чьи данные были изменены, это работает. В вашем методе контроллера добавьте:
app()->singleton('touristsCollector', function ($app) {
$collector = new \stdClass;
$collector->updated = [];
return $collector;
});
for($i = 0; $i < $number_of_tourists; $i++) {
$tourist = Tourist::updateOrCreate(
['doc_number' => $request['doc_number'][$i]],
$tourist_to_update
);
}
$collector = resolve('touristsCollector');
var_dump( $collector->updated ); // Only updated tourists which have data changed
Это в основном добавит в контейнер приложения стандартный класс PHP, который будет собирать всех обновленных туристов из модельного события. В вашей модели добавьте это:
protected static function boot()
{
parent::boot();
static::updated(function ($model) {
$collector = resolve('touristsCollector');
$collector->updated[] = $model;
});
}
Это в основном позволит получить класс PHP из контейнера приложения и добавить модель туриста, только если некоторые его свойства были обновлены.
Если вы всегда хотите выполнить определенный код при обновлении строки в туристической таблице, я бы порекомендовал создать наблюдателя для прослушивания 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);
}
Если модель была создана свойство wasRecentlyCreated
будет установлено значение true, поэтому вы можете проверить, является ли модель новой или обновленной:
$updated = [];
for($i = 0; $i < $number_of_tourists; $i++) {
$currentTourist = ['doc_number' => $request['doc_number'][$i]];
$tourist = Tourist::updateOrCreate($currentTourist, $tourist_to_update);
if ( $tourist->wasRecentlyCreated ) {
continue; // Go to next loop if this tourist was created now
}
$updated[] = $tourist;
}