【问题标题】:How to return false when chaining methods链接方法时如何返回false
【发布时间】:2011-12-13 16:50:33
【问题描述】:

我有一个使用方法链接的验证类。我希望能够像这样使用TRUE/FALSE 进行单次检查:

if ($obj->checkSomething()) {}

还有这样的链式方法:

if ($obj->checkSomething()->checkSomethingElse()) {}

然而问题是,如果一个方法返回FALSE,它不会返回一个对象,从而破坏了以这个错误结束的方法链接:

Fatal error: Call to a member function checkSomething() on a non-object in ...

我是否必须选择单个方法返回调用或方法链接,或者是否有解决方法?

【问题讨论】:

  • 这是一个很好的迹象,为什么你不应该使用方法链:)

标签: php validation error-handling return-value


【解决方案1】:

一个想法是设置一个内部标志来指示成功或失败,并通过另一种方法访问它,同时在每个方法中检查该标志,如果已设置则不执行任何操作。例如:

class A {
    private $valid = true;

    public function check1() {
        if (!$this->valid) {
            return $this;
        }
        if (!/* do actual checking here */) {
            $this->valid = false;
        }
        return $this;
    }
    public function check2() {
        if (!$this->valid) {
            return $this;
        }
        if (!/* do actual checking here */) {
            $this->valid = false;
        }
        return $this;
    }
    public function isValid() {
        return $this->valid;
    }
}

// usage:

$a = new A();

if (!$a->check1()->check2()->isValid()) {
    echo "error";
}

为了尽量减少每个函数中的样板检查,您还可以使用魔术方法__call()。例如:

class A {
    private $valid;
    public function __call($name, $args) {
        if ($this->valid) {
            $this->valid = call_user_func_array("do" . $name, $args);
        }
        return $this;
    }
    private function docheck1() {
        return /* do actual checking here, return true or false */;
    }
    private function docheck2() {
        return /* do actual checking here, return true or false */;
    }
    public isValid() {
        return $this->valid;
    }    
}

用法同上:

$a = new A();

if (!$a->check1()->check2()->isValid()) {
    echo "error";
}

【讨论】:

  • 我自己也想过这个问题,但希望有一种更简单的方法来处理这个问题。将查看是否有一些 PHP 大师提出了更简单的解决方案,否则您的答案将被接受。谢谢!
【解决方案2】:

我相信您希望根据验证结果将实例评估为真/假。

虽然有些语言允许您覆盖实例的布尔值,但 php 不允许(除了强制转换为字符串,请参阅 PHP 的 Magic Methods)。

另外,PHP 手册中的the booleans page 有一个评估为假的事物列表,但它也没有提供任何覆盖行为的方法。

话虽如此,我建议按照 JRL 的想法,构建一个验证规则链,然后使用返回 if 语句中所需布尔值的函数“执行”它。

【讨论】:

    【解决方案3】:

    也许你可以将它们封装在一个子类中。

    例如如果你有

    class Validate {
        public function checkSomething($data) {
            if ($data === $valid) {
                return true;
            } 
            return false;
        }
        public function checkSomethingElse($data) {
            if ($data === $valid) {
                return true;
            } 
            return false;
        }
    }
    

    你可以这样做:

    class ValidateChain extends Validate {
        protected $valid = true;
    
        public function checkSomething($data) {
            if (false === parent::checkSomething($data)) {
                $this->valid = false;
            }
            return $this;
        }
        public function checkSomethingElse($data) {
            if (false === parent::checkSomethingElse($data)) {
                $this->valid = false;
            } 
            return $this;
        }
        public function getIsValid() {
            return $this->valid;
        }
    }
    
    $v = new ValidationChain();
    $valid = $v->checkSomething()->checkSomethingElse()->getIsValid();
    

    又快又脏,E&OE。而且您可能需要添加一种方法来找出哪些位无效等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-20
      • 2012-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-26
      • 2011-06-09
      • 1970-01-01
      相关资源
      最近更新 更多