链接方法时如何返回false

时间:2011-10-23 19:52:54

标签: php validation error-handling return-value

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

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

但是这样的连锁方法:

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

然而问题是,如果一个方法返回FALSE,它将不会发回一个对象,从而打破以此错误结束的方法链:

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

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

3 个答案:

答案 0 :(得分:8)

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

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()。 E.g:

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

答案 1 :(得分:1)

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

虽然有些语言允许你覆盖实例的布尔值,但php却没有(除了转换成字符串,就是这样。请参阅PHP的Magic Methods)。

此外,PHP手册中的the booleans page列出了评估为false的内容,但它没有提供任何覆盖行为的方法。

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

答案 2 :(得分:0)

你可以将它们包装在一个子类中。

e.g。如果你有

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。你可能需要添加一种方法来找出哪些位无效等等。