首页 > 解决方案 > 在 PHP 中链接检查的优雅方式

问题描述

假设您有一个通用的验证功能,并且您必须对输入进行几次子检查。它们中的每一个也返回布尔值。看这个虚构的:

private function hasValidContent(string $content) : bool
{
    $isValid = false;
    $isValid = $this->hasMoreThanOneChar($content);
    $isValid = $this->hasValidCharacters($content);
    $isValid = $this->hasCapitalLetters($content);
    ...
    
    return $isValid;

}

当然,上面的代码不会起作用,因为每次下一次检查都会覆盖前一次的评估。

但是,当第一次检查导致 时,如何停止进一步检查false?例如,如果它的内容不超过一个字符,那么它应该在hasMoreThanOneChar函数之后停止并hasValidContent立即将方法返回为 false。

是的,当然,您可以在每个方法调用后检查表达式是否变为 false,但这很尴尬,而且开销和重复很多。

||如果有数千个或&&类似的情况,单次执行它也感觉非常难看

return $this->checkA($content) 
   && $this->checkB($content)
   && $this->checkC($content)
  ...;

再多表达几句后,可读性会受到影响。

另一个经常提到的方法可能是使用异常

private function hasValidContent(string $content) : bool
{
    try {
        $this->hasMoreThanOneChar($content);
        $this->hasValidCharacters($content);
        $this->hasCapitalLetters($content);
        ...
    }
    catch {
        return false;
    }
    return true;

}

private function hasMoreThanOneChar(string $string) : void {
    if(count($string) < 2 ) {
      throw new HasNotMoreThanOneCharException(...)
    }
}

但我也认为这不是一个优雅的解决方案,因为验证东西并没有什么特别之处。

所以我的问题:

有什么优雅的模式吗?我可以搜索任何关键字吗?

标签: phpsyntaxcoding-style

解决方案


创建一个包含您要执行的所有验证的数组。数组的每个元素都必须是可调用的。迭代并提前退出。如果所有验证者都通过了,那就很好。

private function hasValidContent(string $content) : bool
{
    $validators = [
        // instance method
        [$this, 'hasMoreThanOneChar'],
        // callable class
        new class {
            public function __invoke(string $content)
            {
                return ...;
            }
        },
        // anonymous function
        function (string $content): bool {
            return ...;
        }
    ];

    foreach ($validators as $validate) {
        if (!$validate($content)) {
            return false;
        }
    }

    return true;
}

推荐阅读