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;
}
Другие вопросы по тегам