Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用克隆的PHP伪不可变对象_Php_Laravel_Immutability - Fatal编程技术网

使用克隆的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
,因为验证器自己处理它。嗯,我不太明白“仅仅使用”一个类。您需要以某种方式实例化它,除非它是静态的。