链接的PHP控件


Chained PHP controls

我正在制作一个表单验证类,目前它的工作方式是这样的。

$validator->setVar($_POST['Username'])
          ->standardFilter(array('XSS', 'SQL_INJECTION'))
          ->customRegex()
          ->replace('This', 'With this')
          ->getResult();

虽然它在像这样链接时工作得很好,但我无法存档以下结果。

$validator->setVar($_POST['Username'])
          ->isValidEmail()
          ->isValidPhoneNumber()
          ->isSet()
          ->isNull()
          ->getResult()

例如,脚本返回以下值

->isValidEmail() (true)
->isValidPhoneNumber() (true)
->isSet() (false)

基本上,我将制作一个数组,根据每个函数的结果用true/false填充它,然后在数组中查找特定的值(false)。如果它存在,则不管链的其余部分如何,该类都将返回false。(或者我可以覆盖变量,在这里不重要。)

然而,我希望$validator在从函数中得到false后停止链接。假设它从isSet()接收到一个false。它不应该执行isNull()和getResult(),因为我们已经有一个失败的检查。

如何在PHP中存档?

TL;DR:

var_dump($validator->setVar('Test message')->isInteger()->setTrue());
                                             //false     //true
Output: false, because once isInteger() failed, rest of the chain isn't executed.

如何在PHP中存档?

没有什么比好的源代码更值得学习的了。我建议探索Zend框架的Validation类。它提供了与您描述的相同的链接功能。

更多的源代码检查是Valid()。

试试这样的

class FooBar
{
  private $SomethingWrong = false;
  function Bar()
  {
    if( $this->SomethingWrong )
      throw new Exception('SomeThing is wrong');
    return $this;
  }
  function Foo()
  {
    return $this
  }
}
$foobar = new FooBar();
$foobar->Bar()
       ->Foo();

由于Bar()中的异常,Foo()部分将不会执行。

当然,也有一些变化。如果你不想要一个异常,而是一个无声的不执行,你可以试试这个:

class FooBar
{
  private $SomethingWrong = false;
  function Bar()
  {
    $this->SomethingWrong = true;
    return $this;
  }
  function Foo()
  {
    if( !$this->SomethingWrong )  {
      // do my stuff
    }
    return $this
  }
}

在任何语言中,唯一的方法就是抛出异常。您不能返回验证器对象(这是链接所必需的),也不能返回true或false,同时还要进行链接。也就是说,我不主张以这种方式使用例外情况。我完全同意vascowhite在下面的评论。

与其让它停在链的中间,为什么不将isSetisNull等方法视为指示,告诉验证器要检查什么。然后在链的末尾调用一个validate方法。validate方法可以根据验证器状态(由其他方法设置)执行验证。validate方法也可以返回true或false,或者自定义状态对象,并返回验证结果。

您可以抛出一个自定义异常,从而中止代码执行,而不是返回值。在代码中添加一个try-catch块,处理您的异常,一切正常。

编辑:你还可以做的是一点魔术,而不是真正的推荐。但很高兴知道,这在php中是可能的,所以最好使用Exceptions

class PassThroughValidator extends ...
{
    private $val;
    public function __construct($result)
    {
        $this->val = $result;
    }
    public function __call($name, $arguments)
    {
        return $this;
    }
    public function getResult()
    {
        return $this->val;
    }
}
class EmailValidator extends ...
{
    function isMail()
    {
        if (...) {
            // do something here
            return $this;
        }
        // set Result to false or something similar
        return new PassThroughValidator($this->getResult());
    }
}

考虑到链的每个步骤中返回的值都是一个对象,您不能让其中一个链式方法返回true/false。它必须始终返回一个对象实例。所以我想你需要做的是在对象上添加一些属性来指示不应该进行验证,如果设置了属性,只需忽略验证尝试并按原样返回对象。

因此,也许这是一个简化的形式,只显示一个这样的验证:

class validator {
    protected $ignore_validations = false;
    protected $value = null;
    protected $is_null;
    public function isNull () {
        if(true === $this->ignore_validations) {
            return $this;
        } else if(is_null($this->value)) {
            $this->is_null = true;
            $this->ignore_validations = true;
            return $this;
        } else {
            $this->is_null = false;
            return $this;
        }
    }
}