2015-07-13 31 views
0

我需要運行一些代碼,當我的模型之一被保存(創建/更新)或刪除。什麼是最好的方式來做到這一點?在Laravel 5.2中捕獲保存和刪除的最可靠方法是什麼?

有三種不同的方法,我所知道的:

  1. Override the save and delete methods on the model
  2. Add creating/updating/deleting callbacks in the boot method
  3. Bind an observer in the boot method

我還沒有看到這些比較和對比,所以我不不知道有什麼區別。我擔心這些事件在某些情況下不會發生。

例如,在Django中,如果逐個刪除模型,但不是批量刪除,則只刪除火警。


要清楚,我正在尋找一個比較和對比這些(或其他)方法的答案 - 不是簡單地建議做同樣的事情的更多的方式。

+0

與Django中的Eloquent一樣:「在通過Eloquent執行批量刪除語句時,刪除和刪除的模型事件不會爲已刪除的模型觸發,這是因爲在執行delete語句時模型從未被實際檢索到。 「 –

+0

@jakubwrona這三種方法都不支持大規模刪除?好。還有什麼我應該注意的嗎?效率有差異嗎?他們中的任何一個比其他人更強大/更不可能突破?或者這只是一個偏好問題?爲什麼有很多方法可以做同樣的事情? – mpen

回答

1

的三種方法,並通過四指@joko其他方法。可能還有更多,但讓我們關注4種方法。

讓我描述你一一:

1)覆蓋在模型上

在這種方法中使用的是OOPD方法重載的保存和刪除的方法。您正在重寫Laravel的內部方法save,並通過在其上定義自己的save方法來添加附加代碼。這應該避免,因爲Laravel不斷髮展,並且可能發生的事情是,如果重大變更完成,就像事情開始失敗一樣,假設將來使用任何其他方法替代save方法來保存記錄。然後,您將不得不創建另一種方法來覆蓋該新方法。此處編寫代碼可能會增加您的模型類文件。你的模型可能會繼續處理他不應該處理的事情(例如:發送電子郵件)。 應避免使用此方法。

2)添加創建/更新/刪除回調的引導方法

在這裏,你是在模型的啓動方法定義代碼。只有在事件需要處理很少的代碼/事情時才應該使用此方法。這種方法的缺點是它使代碼更加複雜和混亂,因爲你可能像編寫函數一樣編寫所有的邏輯。假設你在創建之前和創建之後必須做些什麼。你的boot方法會增長。

3)綁定在引導方法

該方法的觀察者是相當不錯的。你創建一個觀察者類來處理Laravel事件應該發生的事情。它使代碼更加清潔並易於維護。

示例:假設您必須在這些方法中編寫creating,saving,saved,deleting中的代碼。在這種情況下,方法1)和方法2)也不會好做法,因爲在

方法1:我們必須創建此4種方法,並覆蓋它們,以及支持他們Laravel的未來版本。在這種情況下,模型中的代碼也將增長,因爲重寫此方法

方法2:在這種情況下,您boot方法也會增長,所以你型號的文件將成爲一個代碼的垃圾。

在方法1和2中,還記得它不是你的模型的職責來完成你要編寫的許多東西。就像創建用戶時發送電子郵件一樣。這些代碼最終可能會以created方法寫入。

現在假設您有場景需要在created事件上向用戶發送電子郵件,以及您需要在客戶CRM中創建用戶的登錄日誌用戶。那麼你將不得不用相同的方法編寫代碼。也許,你可能不會遵循單一責任原則。我們該怎麼辦?參見方法4.

4)Other method suggested by @joko

,我在方法4的最終建議的情況。您可以發送電子郵件給用戶,並在創建時將其登錄到客戶CRM中。然後你的方法會做2件事(發送電子郵件和登錄CRM)。它可能不遵循單一責任原則。如果更好,我們可以解耦他們兩個。然後來這個方法。

class EventServiceProvider extends ServiceProvider 
{ 
    /** 
    * The event listener mappings for the application. 
    * 
    * @var array 
    */ 
    protected $listen = [ 
     'eloquent.saved: App\User' => 'App\Listeners\SendWelcomeEmailToUser' 
     'eloquent.saved: App\User' => 'App\Listeners\LogUserInCRM' 
    ]; 
} 

創建兩個listener classes

class SendWelcomeEmailToUser 
{ 
    public function handle(User $user){ 
     // Write code to send email 
    } 
} 

class LogUserInCRM 
{ 
    public function handle(User $user){ 
     // Write code to log 
    } 
} 

通過這個就可以分離出代碼,使他們更乾淨。

我一般都喜歡這種方法,它的模式乾淨。它也讓你更好地認識事件發生時實際發生的事情。它成爲Event to Listener映射的單一點。

1

您可以爲模型的每個創建/更新創建事件處理程序,例如添加以緩存剛剛保存到數據庫或將要保存到數據庫的模型數據,更容易在沒有選擇查詢調用的情況下檢索, while刪除調用,使用忘記緩存處理程序事件上給定的鍵來刪除緩存以及從數據庫中刪除。

3

這只是我以前提到的幾種方法的看法。

  1. 覆蓋模型上的保存和刪除方法(如果覆蓋它,然後方法Laravel變化知名度的下一次更新您的代碼不試。工作,它會拋出異常或PHP錯誤。你必須修改它再工作)
  2. 添加創建/更新/刪除回調的引導方法(在Laravel 4存在,您應該在Laravel檢查一遍使用事件和監聽器)
  3. 綁定在開機方法的觀察者5也許不同的實現(存在在Laravel 4中,你應該在Laravel 5中再次檢查它,也許使用Event和Listener的不同實現)

我想你應該使用Laravel提供的Event和Listener。它可能仍然在下一個Laravel更新。我假設事件和偵聽器是Laravel中的一個小變化區域,並且可能只是改變了不同的方法實現。

Laravel應該有哪些Laravel的一部分將發展爲重大變化區域(大修改)或微小的變化區域(稍加修改)發展分配的計劃。如果您嘗試更改或覆蓋主要更改區域,則它將無法在下一次Laravel更新中使用。

你可以註冊事件和聽衆爲保存和刪除記錄。 Laravel有fireModelEvent方法模型(Illuminate \ Database \ Eloquent \ Model)它觸發特定的Laravel事件。如果您已註冊Event,調度員(Illuminate \ Events \ Dispatcher)將執行Event的監聽者。

文檔關於Laravel活動:

https://laravel.com/docs/5.3/events

https://laravel.com/docs/5.2/events

我假設你有YourModel作爲模型,然後做下面的下面的操作。

  • 註冊事件和監聽器。打開app \ Providers \ EventServiceProvider.php,然後將Event和Listener添加到YourModel的EventServiceProvider.listen屬性中,或者按照Laravel Documentation以其他方式創建事件。
 

class EventServiceProvider extends ServiceProvider 
{ 
    /** 
    * The event listener mappings for the application. 
    * 
    * @var array 
    */ 
    protected $listen = [ 
     ... 
     'eloquent.saved: App\YourModel' => [ 
      'App\[email protected]', 
     ], 
    ]; 
} 
 
  • 在App \ YourModel添加 eventSaved方法監聽的事件,所以你可以做特定的動作保存或刪除後。
 

class YourModel extends Model 
{ 
    public function eventSaved(){ 
     // You can add your code to catch save here 
    } 
} 
 
1

我偏愛手動做的事情時,你需要知道他們究竟是如何完成的。我最近使用這個Laravel樣板啓動一個項目,我喜歡的方式,他們手動觸發存儲庫中的事件時,模型更新:

https://github.com/rappasoft/laravel-5-boilerplate/blob/master/app/Repositories/Backend/Access/User/EloquentUserRepository.php

由於模型應該總是通過存儲庫進行更新,你總能得到手動決定如何處理事件。當多個模型被刪除時,您可以觸發您自己的事件,並據此採取行動。您的所有選項都可以工作,但您只需找到最適合您需求的選項即可。

1

您可以創建抽象Model類來擴展Illuminate\Database\Eloquent\Model類,並且您的所有模型都將擴展此類。通過這樣的實施,您可以對模型進行更多控制。例如

<?php 

namespace App\Base\Database; 


use Illuminate\Database\Eloquent\Model as BaseModel; 

abstract class Model extends BaseModel 
{ 
    public function save(array $options = []) 
    { 
     //your code here 
     return parent::save($options); 
    } 
} 

可以爲Model類的所有方法做到這一點,你也可以加入其他適用於所有車型在您的應用程序

+0

沒錯,但是會爲所有模型啓動 - 我只對一個特定的模型感興趣。 – mpen

+0

@mpen如果你只想在一個模型上使用這個實現,你可以像在我的例子中那樣在你的特定模型中覆蓋保存函數。 – Kliment

+0

確實。這是我的問題中的選項#1。我更有興趣知道這是否比其他兩種方法有什麼優勢。 – mpen

相關問題