2017-02-24 40 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的对象不变性。所以我觉得那里没有问题。

我怀疑你会得到有关半不变性一些意见,虽然,但我个人认为这是一个合理的解决问题的方法