这是一个棘手。简短版本:从您的处理程序中删除您的返回值,并且两个事件都会触发。长版本如下。
首先,我会假设你想键入MyParent
(不myParent
),那你的意思是你的boot
方法是protected
,而不是private
,那你包括在你create
方法调用最终)
。否则,你的代码不会运行。 :)
但是,您描述的问题是真实的。其原因是肯定的雄辩事件被认为是“停止”事件。也就是说,对于某些事件,如果从事件处理程序返回任何非空值(无论是闭包还是PHP回调),则该事件将停止传播。你可以在调度员看到这个
#File: vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php
public function fire($event, $payload = array(), $halt = false)
{
}
看到第三个参数$halt
?后来,当调度程序调用的事件侦听器
#File: vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php
foreach ($this->getListeners($event) as $listener)
{
$response = call_user_func_array($listener, $payload);
// If a response is returned from the listener and event halting is enabled
// we will just return this response, and not call the rest of the event
// listeners. Otherwise we will add the response on the response list.
if (! is_null($response) && $halt)
{
array_pop($this->firing);
return $response;
}
//...
如果停止是true
和回调返回任何,这不是空(true
,false
,一个sclaer值,array
,一个object
),该fire
方法短路与return $response
,事件停止传播。这超出了标准“返回false
停止事件传播”。有些事件已经停止了。
那么,哪些模型事件会停止?如果你看一下在基础雄辩模型类fireModelEvent
定义(Laravel别名这是Eloquent
)
#File: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
protected function fireModelEvent($event, $halt = true)
{
//...
}
你可以看到模特的事件默认至停止。所以,如果我们通过模型对触发事件中,我们看到做停止的事件
#File: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
$this->fireModelEvent('deleting')
$this->fireModelEvent('saving')
$this->fireModelEvent('updating')
$this->fireModelEvent('creating')
和事件不停止的
#File: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
$this->fireModelEvent('booting', false);
$this->fireModelEvent('booted', false);
$this->fireModelEvent('deleted', false);
$this->fireModelEvent('saved', false);
$this->fireModelEvent('updated', false);
$this->fireModelEvent('created', false);
正如你所看到的,creating
是一个暂停事件,这就是为什么返回任何值,即使true
,停止事件,你的第二个听众没有触发。当Model类想要用事件的返回值做某些事情时,通常会使用暂停事件。具体从回调creating
#File: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
protected function performInsert(Builder $query)
{
if ($this->fireModelEvent('creating') === false) return false;
//...
如果返回false
,(NOT NULL),Laravel实际上会跳过执行INSERT
。再次,这是与标准停止事件传播不同的行为,返回错误。在这四个模型事件中,返回false
也将取消他们正在侦听的动作。
删除返回值(或return null
),你会很开心。
AlanStorm不错! – 2014-10-08 10:02:49
太棒了!我想如果我觉得足够努力,这是有道理的。如果一个听众取消创作,其他听众不应该开火。我真的很惊讶,返回“真实”也停止。 Anywho,伟大的解释AlanStorm - 谢谢! – Anthony 2014-10-09 13:54:27
@Anthony这有点奇怪/不明显,但这里并不容易赢。这就是为什么像Drupal这样的系统有事件的事件系统,以及需要操作数据的事件的“钩子”系统。 – 2014-10-09 16:50:50