Laravel Eloquent Events - implement to save model if Updated

一世执手 提交于 2019-12-31 07:06:33

问题


I have such code in the controller:

for($i=0; $i<$number_of_tourists; $i++) {

$tourist = Tourist::updateOrCreate(['doc_number' => $request['doc_number'][$i]],
$tourist_to_update);

}

so, the updateOrCreate method can 1) Update record, 2) Create a new one 3) Leave record untouched if $tourist_to_update equals to what's already in the DB.

I want to save $tourist_to_update into $array[] only when a record in 'tourist" table is being updated (not when a new record created or nothing changes).

As I know, there are Eloquent events https://laravel.com/docs/5.4/eloquent#events which have updating and updated events, which seem to match my needs.

The problem is I watched&read several tutorials and still don't understand how to use them.

I know how-to-register a Eloquent event in Tourist model:

protected static function boot()
{
    parent::boot();

    static::updating(function ($model) {

    });
}

Could anyone explain how can I achive my goal with Eloquent events?

Thank you in advance.


回答1:


This is a bit more complex approach, but if you want to get only updated records which have their data changed this is working. In your controller method add:

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

This will basically add to the app container a standard PHP class which will collect all the updated tourists from the model event. In your model add this:

protected static function boot()
{
    parent::boot();

    static::updated(function ($model) {
        $collector = resolve('touristsCollector');
        $collector->updated[] = $model;
    });
}

This will basically get the PHP class from the app container add the tourist model only if some properties of it have been updated.




回答2:


If the model has been created the property wasRecentlyCreated will be set to true, so this is how you can check if the model is new or updated:

$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;
}



回答3:


If you always want to execute a specific code when a row in tourist table was updated, I would recommend to create an observer to listen for updated or create calls.

<?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
    }
}

All you have to do is to register the observer in AppServiceProvider like this:

public function boot()
{
    Tourist::observe(\App\Observer\TouristObserver::class);
}


来源:https://stackoverflow.com/questions/45698659/laravel-eloquent-events-implement-to-save-model-if-updated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!