laravel Model 事件阻止listen

1. Laravel 的事件若是走Listener類,則Handler方法返回false 會阻止事件繼續下發;php

Illuminate\Events\Dispatcher;
public function dispatch($event, $payload = [], $halt = false)
{
    // When the given "event" is actually an object we will assume it is an event
    // object and use the class as the event name and this event itself as the
    // payload to the handler, which makes object based events quite simple.
    list($event, $payload) = $this->parseEventAndPayload(
        $event, $payload
    );

    if ($this->shouldBroadcast($payload)) {
        $this->broadcastEvent($payload[0]);
    }

    $responses = [];

    foreach ($this->getListeners($event) as $listener) {
        $response = $listener($event, $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 ($halt && ! is_null($response)) {
            return $response;
        }

        // If a boolean false is returned from a listener, we will stop propagating
        // the event to any further listeners down in the chain, else we keep on
        // looping through the listeners and firing every one in our sequence.
        if ($response === false) {
            break;
        }

        $responses[] = $response;
    }

2.若是是Model的內置事件,則return false 不會阻止已註冊事件的處理;可是經過Model的 oop

/**
 * The event map for the model.
 *
 * Allows for object-based events for native Eloquent events.
 *
 * @var array
 */
protected $dispatchesEvents = [];

此屬性算爲自定義事件列表,在觸發處理後返回false 會打斷事件的下發處理,見:ui

/**
 * Fire the given event for the model.
 *
 * @param  string  $event
 * @param  bool  $halt
 * @return mixed
 */
protected function fireModelEvent($event, $halt = true)
{
    if (! isset(static::$dispatcher)) {
        return true;
    }

    // First, we will get the proper method to call on the event dispatcher, and then we
    // will attempt to fire a custom, object based event for the given event. If that
    // returns a result we can return that result, or we'll call the string events.
    $method = $halt ? 'until' : 'fire';

    $result = $this->filterModelEventResults(
        $this->fireCustomModelEvent($event, $method)
    );

    if ($result === false) {
        return false;
    }

    return ! empty($result) ? $result : static::$dispatcher->{$method}(
        "eloquent.{$event}: ".static::class, $this
    );
}

 

對於Model內置事件:

好比某個Model的Updated事件,裏面作了一個又會觸發該model的update事件,會死循環直到最大執行時間。this

若是通常認爲return false;能夠起到做用,可是不能夠,只有自定義的事件能夠起做用,內置的不可行。spa

方案一:

stackoverflow上rest

//updated listener裏面 


            //禁止事件分發器
            $dispatcher = $model->getEventDispatcher();
            $model->unsetEventDispatcher();
            //此處爲可觸發updated事件的業務code
            $model->update();
            //完事恢復現場
            $model->setEventDispatcher($dispatcher);

相似的:code

方案二:

$event = 'eloquent.updated: '. get_class($model);//注意冒號後有一個空格
$listener = $model->getEventDispatcher()->getListeners($event);
$model->getEventDispatcher()->forget($event);

//此處爲可觸發updated事件的業務code
$model->update();
//此處爲可觸發updated事件的業務code end

$model->getEventDispatcher()->listen($event, $listener);
相關文章
相關標籤/搜索