Ищу что-то вроде break для шлейфов.
Вот пример кода (с использованием лайма 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(), чтобы это произошло?






Вы можете использовать Исключения PHP:
// 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();
Я узнал, что лайм на самом деле ловит любое исключение и останавливает его продолжение, как я и искал.
Просто верните другой класс, который будет возвращать $ 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
В итоге я использовал это, чтобы отслеживать методы, которые не работают. Это более ясно о том, что он делает. Огромное спасибо!
Ответ 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;
}
}
Его можно поместить в родительский класс, чтобы не дублировать этот код.
Вам нужно будет вызвать $ browser-> start () -> method () -> method2 (); каждый раз. Цепочка, возвращающая другой класс / объект, является проблемой только в том случае, если вы ожидали что-то сделать с объектом, возвращенным одним из методов. Но тогда и ваш метод не сработает.
ну, очевидно, вы бы инициализировали $ halt как ложь. Ваше решение было бы не лучшим, если бы вы сделали что-то вроде $ a = $ b-> func1 () -> func2 () -> stop () -> func3 (); ... поскольку $ a будет объектом NoMethod .
Эмм, $ b - это то, чем будет $ a, поэтому в этом нет смысла, вы можете просто сделать $ a = $ b = new Object (); Ваш аргумент ошибочен.
Это интересная техника, я бы ни о чем не подумал.