我陷入了一个奇怪的问题.感觉就像在Laravel中,你不允许多个模型观察者听同一个事件.就我而言:
父模型
class MyParent extends Eloquent {
private static function boot()
{
parent::boot();
$called_class = get_called_class();
$called_class::creating(function($model) {
doSomethingInParent();
return true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
儿童模特
class MyChild extends myParent {
private static function boot()
{
parent::boot();
MyChild::creating(function($model) {
doSomethingInChild();
return true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,如果我这样做:
$ instance = MyChild :: create();
...行doSomethingInChild()不会触发.doSomethingInParent(),确实如此.
但是,如果我在 MyChild :: creating()之后移动子进程中的parent :: boot(),它确实有效.(我没有确认doSomethingInParent()是否触发,但我认为它没有)
Laravel可以在Model :: creating()中注册多个事件吗?
Ala*_*orm 18
这个很棘手.简短版本:从您的处理程序中删除您的返回值,这两个事件都将触发.长版如下.
首先,我假设您打算键入MyParent
(而不是myParent
),表示您的boot
方法是protected
,而不是private
,并且您)
在create
方法调用中包含了final .否则您的代码不会运行.:)
但是,您描述的问题是真实的.其原因是某些Eloquent事件被认为是"停止"事件.也就是说,对于某些事件,如果从事件处理程序返回任何非null值(无论是闭包还是PHP回调),该事件将停止传播.您可以在调度程序中看到这一点
#File: vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php
public function fire($event, $payload = array(), $halt = false)
{
}
Run Code Online (Sandbox Code Playgroud)
看到第三个参数$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;
}
//...
Run Code Online (Sandbox Code Playgroud)
如果停止true
并且回调返回任何非空的(true
,false
sclaer值,an array
,an object
),则该fire
方法与a短路return $response
,并且事件停止传播.这超出了标准"返回false
停止事件传播".有些事件已经停止了.
那么,哪些模型事件停止了?如果你看一下fireModelEvent
基础雄辩模型类中的定义(Laravel别名为Eloquent
)
#File: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
protected function fireModelEvent($event, $halt = true)
{
//...
}
Run Code Online (Sandbox Code Playgroud)
您可以看到模型的事件默认为暂停.所以,如果我们通过模型对触发事件中,我们看到的事件做停止的
#File: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
$this->fireModelEvent('deleting')
$this->fireModelEvent('saving')
$this->fireModelEvent('updating')
$this->fireModelEvent('creating')
Run Code Online (Sandbox Code Playgroud)
和不停止的事件是
#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);
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,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;
//...
Run Code Online (Sandbox Code Playgroud)
如果你false
从回调中返回(不为空),Laravel实际上会跳过执行INSERT
.同样,这与标准停止事件传播的不同行为是返回false.在这四个模型事件的情况下,返回false
也将取消他们正在侦听的操作.
删除返回值(或return null
),你会很高兴.