使用克隆的PHP伪不可变对象
我希望创建一个自定义验证器。但是我不想每次都调用使用克隆的PHP伪不可变对象,php,laravel,immutability,Php,Laravel,Immutability,我希望创建一个自定义验证器。但是我不想每次都调用new,因为这使得测试更加困难。我还认为App::make有点难看。我只想注入我的自定义验证器并使用它 关于如何实现这一点,我的想法是使用clone。调用validate方法将设置克隆的属性,而不是$this。这样,类的DI版本保持不变。通过这种方式进行测试/模拟也非常容易 这是一种合适的模式/我是否应该使用new 我的自定义验证器 class CustomValidator { protected $rules = [ '
new
,因为这使得测试更加困难。我还认为App::make
有点难看。我只想注入我的自定义验证器并使用它
关于如何实现这一点,我的想法是使用clone
。调用validate方法将设置克隆的属性,而不是$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
}
clone
是完全有效的,通常用于流畅的语法API中的对象不变性。因此,我认为没有问题
虽然我怀疑你会得到一些关于半不变性的评论,但我个人认为这是解决你问题的合理方法好吧,如果
App::make
看起来很难看,那么Laravel可能不是最好的选择。使用容器是一种非常惯用的方法,框架在很大程度上依赖于它。默认情况下,bind
注册非共享服务,即从容器中获得一个新实例。这不仅仅是因为App::make
看起来很难看。IMO-通过使用克隆,它减少了出错的可能性。e、 g.忘记使用App:make
或忘记使用new
将导致未来迭代中出现错误。e、 g.通过填充错误
数组,以及后续调用中剩余的人工制品,甚至代码中的其他地方。我不太清楚忘记App::make
比忘记克隆
更糟糕,但在您的情况下,这确实是个品味问题。一般来说,克隆略有不同,因为克隆共享相同的注入对象实例,这可能是一种理想的行为,也可能不是。使用该类时,您需要记住App::make(CustomValidator::class)
或new CustomValidator
——而不仅仅是使用它。当你在自定义验证器
中克隆时,你可以忘记应用程序::make
和new
,因为验证器自己处理它。嗯,我不太明白“仅仅使用”一个类。您需要以某种方式实例化它,除非它是静态的。