链式PHP控件

时间:2012-09-11 17:57:45

标签: php

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

$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一旦从函数中获取错误就停止链接。假设它从isSet()收到错误。它不应该执行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中实现这个目标?

5 个答案:

答案 0 :(得分:5)

没有什么比学习好的源代码更好的了。我建议探索Zend Framework的Validation classes。它提供了您描述的相同chaining functionality

... More source code具体检查isValid()。

答案 1 :(得分:2)

尝试这样的事情

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
  }
}

答案 2 :(得分:2)

用任何语言执行此操作的唯一方法是抛出异常。您无法返回验证器对象(这是链接所必需的),并且在进行链接工作时也会返回true或false。也就是说,我主张以这种方式使用例外。我完全赞同下面的vascowhite的评论。

为什么不考虑isSetisNull等方法作为告诉验证者要检查的内容的指令,而不是让它停在链的中间。然后在链的末尾调用validate方法。 validate方法可以基于验证器状态执行验证(由其他方法设置)。并且validate方法也可以返回true或false,或者自定义状态对象,以及验证结果。

答案 3 :(得分:1)

您可以抛出自定义异常,而不是返回值,这会中止代码执行。 在代码中添加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());
    }
}

答案 4 :(得分:0)

考虑到链的每个步骤中返回的值是一个对象,您不能让其中一个链接方法返回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;
        }
    }
}