2017-08-15 52 views
0

我有在控制器這樣的代碼:Laravel雄辯的活動 - 實現節省模式,如果更新

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保存到$ []數組只有在「旅遊」表中的記錄被更新(一個新的記錄創建或沒有什麼變化不是當)。

據我所知,有口才很好事件https://laravel.com/docs/5.4/eloquent#events具有更新更新事件,這似乎符合我的需要。

問題是,我看着&讀幾個教程,仍然不知道如何使用它們。

我知道如何對註冊在旅遊模型雄辯事件:

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

    static::updating(function ($model) { 

    }); 
} 

任何人都可以解釋我怎麼能achive我的目標與雄辯的事件?

預先感謝您。

+0

所以,你要創建一個新的陣列'$ array'其中只包含了哪些更新的記錄? – TheFallen

+0

@ TheFallen是的:)完全! –

回答

1

這是一個比較複雜的方法,但如果你只想得到更新的記錄,其數據發生了變化,這是行得通的。在你的控制器方法中添加:

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類添加只有當它的一些特性已經被更新的旅遊模式。

+0

哇,這就是我正在尋找 - 使用雄辯模型來完成這件事!:)你真的是主人!:)我有一些問題,但我看到沒有區別,如果我改變'靜態:更新'爲'靜態:更新'。那麼有什麼區別?:) –

+0

我在哪裏可以閱讀更多關於'app() - > singleton'和'\ stdClass'?:) –

+1

@SergejFomin,'updating'事件即使屬性相同也會觸發,'updated'只有在數據發生了一些變化時纔會觸發,所以你需要'updated'事件。 – TheFallen

0

如果模型已經建立物業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; 
} 
+0

謝謝你,TheFallen。但我認爲有一個問題。 'updateOrCreate',除了更新和創建之外,還有第三個行爲: 3)如果$ tourist_to_update等於數據庫中已有的內容,請保持記錄不變。我認爲你的代碼將添加一個已經在db中並且不需要更新或創建的遊客到$ updated []數組。我剛剛實現了你的代碼。是的,它確實添加不變的遊客陣列$更新...:( –

+1

@SergejFomin,你是正確的,只有更新的,你可以比較'updated_at'時間戳到當前時間或檢查我的其他答案。 – TheFallen

0

如果您總是希望在旅遊表中的某一行更新時執行特定的代碼,我會建議您創建一個observer來收聽updatedcreate來電。

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