這是一個棘手。簡短版本:從您的處理程序中刪除您的返回值,並且兩個事件都會觸發。長版本如下。
首先,我會假設你想鍵入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