2017-02-24 18 views
0

我希望創建一個自定義驗證器。但我不想每次都致電new,因爲這會使測試更加困難。我也認爲App::make是一個有點醜陋。我只想依賴注入我的自定義驗證器並使用它。使用克隆PHP僞不可變對象

我對如何做到這一點的想法是使用clone。調用驗證方法將設置克隆的屬性,而不是$ this。這樣,該類的DI版本保持不變。這種測試/模擬也很容易。

這是一個合適的模式/我應該只使用new

我的自定義驗證

class CustomValidator 
{ 
    protected $rules = [ 
     'key' => 'required', 
    ]; 

    protected $errors = []; 

    public function validate(array $event): CustomValidator 
    { 
     $v = Validator::make($event, $this->rules); 

     if ($v->fails()) { 
      $copy = clone $this; 
      $copy->errors = $v->errors()->toArray(); 

      return $copy; 
     } 

     return $this; 
    } 

    public function hasErrors(): bool 
    { 
     return !empty($this->errors); 
    } 

    public function getErrors(): array 
    { 
     return $this->errors; 
    } 
} 

用法:

foreach ($events as $event) { 
    // customValidator is immutable. $v is cloned 
    $v = $this->customValidator->validate($event); 

    if ($v->hasErrors()) { 
     // do something with $v->errors(); 
     continue; 
    } 

    // No errors... Do something else 
} 
+0

嗯,如果'應用:: make'長相醜陋,那麼Laravel可能不是最好的選擇。這是使用容器的非常習慣的方式,並且框架嚴重依賴於它。默認情況下'bind'註冊非共享服務,即你從容器中獲得一個新的實例。 –

+0

這不僅僅是'App :: make'看起來很醜。國際海事組織 - 通過使用克隆,它減少了錯誤的可能性。例如忘記「App:make」或忘記「new」會導致未來迭代中的錯誤。例如通過填充'errors'數組,並在隨後的調用中保留這個artefact - 即使在代碼的其他地方。 – Gravy

+0

不太清楚我的理解*忘記*到'App :: make'比'clone'忘記*更糟糕,但在你的情況下它真的很重要。一般來說,克隆是稍微不同的,因爲克隆共享注入對象的相同實例,這可能是也可能不是期望的行爲。 –

回答

0

clone是完全有效的,往往是用於流利syntaxed API的對象不變性。所以我覺得那裏沒有問題。

我懷疑你會得到有關半不變性一些意見,雖然,但我個人認爲這是一個合理的解決問題的方法