2011-10-23 59 views
4

我有一个使用方法链接的验证类。我希望能够做一个检查,以TRUE/FALSE这样的:链接方法时如何返回false

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

而且链的方法是这样的:

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

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

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

我一定要挑无论是单方法返回CA lls或方法链接还是有解决方法吗?

+2

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

回答

8

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

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

+1打我。 –

+0

自己想过这件事,但希望能够解决这个问题。将看看如果一些PHP大师提出了一个更简单的解决方案,否则你的答案将被接受。谢谢! – Seralize

1

我相信你正在寻找有一个实例计算为真/假基于验证的结果。

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

此外,PHP手册中的the booleans page有一个评估为false的事物列表,但它没有给出任何重写行为的方法。这就是说,我会建议按照JRL的想法,构建一个验证规则链,然后用一个函数返回你的if语句中所需的布尔值来执行它。

0

你可能会把它们包装在一个子类中。

例如如果你有

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