我正在寻找类似break
for循环的内容。
这是一些示例代码(使用Symfony的石灰),其中stop()
不会让类继续,I_DONT_WANT_THIS_TO_RUN()
将不会被执行。
$browser->isStatusCode(200)
->isRequestParameter('module', 'home')
->isRequestParameter('action', 'index')
->click('Register')
->stop()
->I_DONT_WANT_THIS_TO_RUN();
$browser->thenThisRunsOkay();
从$this->__deconstruct();
内拨打stop()
似乎无法解决问题。我可以在stop()
内调用一个可以实现这一目标的函数吗?
答案 0 :(得分:10)
您可以使用PHP exceptions:
// This function would of course be declared in the class
function stop() {
throw new Exception('Stopped.');
}
try {
$browser->isStatusCode(200)
->isRequestParameter('module', 'home')
->isRequestParameter('action', 'index')
->click('Register')
->stop()
->I_DONT_WANT_THIS_TO_RUN();
} catch (Exception $e) {
// when stop() throws the exception, control will go on from here.
}
$browser->thenThisRunsOkay();
答案 1 :(得分:6)
只需返回另一个类,它将为每个被调用的方法返回$ this。
示例:
class NoMethods {
public function __call($name, $args)
{
echo __METHOD__ . " called $name with " . count($args) . " arguments.\n";
return $this;
}
}
class Browser {
public function runThis()
{
echo __METHOD__ . "\n";
return $this;
}
public function stop()
{
echo __METHOD__ . "\n";
return new NoMethods();
}
public function dontRunThis()
{
echo __METHOD__ . "\n";
return $this;
}
}
$browser = new Browser();
echo "with stop\n";
$browser->runThis()->stop()->dontRunThis()->dunno('hey');
echo "without stop\n";
$browser->runThis()->dontRunThis();
echo "the end\n";
将导致:
with stop
Browser::runThis
Browser::stop
NoMethods::__call called dontRunThis with 0 arguments.
NoMethods::__call called dunno with 1 arguments.
without stop
Browser::runThis
Browser::dontRunThis
the end
答案 2 :(得分:1)
OIS的答案非常好,但我可以看到,如果对象突然变为其他东西,可能会让人感到困惑。也就是说,您希望在链的末尾,您最终会得到相同的对象。为了避免这个问题,我会添加一个私有变量来告诉班级是否真的要做任何事情。如果班级已经停止,那么每个班级都会立即返回$this
。这为您提供了重新启动执行的额外好处。
class MyClass {
private $halt;
function __call($func, $args) {
if ($this->halt) {
return $this;
} else {
return $this->$func($args);
}
}
private function isRequestParameter() {
// ...
}
public function stop() {
$this->halt = true;
}
public function start() {
$this->halt = false;
}
}
这可以放入父类中,因此您不必复制此代码。