這篇文檔是分析Laravel事件系統(tǒng)。
在生命周期中,注冊event服務(wù)
在Laravel框架生命周期中,在最開始實(shí)例應(yīng)用程序時(shí)
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
Application 類的構(gòu)造函數(shù)里,會(huì)執(zhí)行注冊基礎(chǔ)服務(wù)提供者,其中就有Event事件服務(wù)提供者。
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this));
}
然后執(zhí)行了EventServiceProvider類中的register方法。
public function register()
{
$this->app->singleton('events', function ($app) {
return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
return $app->make(QueueFactoryContract::class);
});
});
}
容器中注冊綁定了events服務(wù),對應(yīng)于new Dispatcher()對象。
自此就有了$app['events']
項(xiàng)目中EventServiceProvider 服務(wù)提供者類
在App\Providers\目錄中有一個(gè)EventServiceProvider ,在這個(gè)服務(wù)提供者里,可以通過$listen 屬性,注冊事件和對應(yīng)的偵聽器
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
Kindle::class=>[JujuListener::class]
];
可以在boot()方法中,手動(dòng)注冊事件.
public function boot()
{
Event::listen(function (PodcastProcessed $event) {
//
});
}
在Laravel框架生命周期運(yùn)行流程里,會(huì)遍歷所有的服務(wù)提供者類,然后執(zhí)行其內(nèi)部定義的register()方法。
EventServiceProvider 的父類是 Illuminate\Foundation\Support\Providers\EventServiceProvider ,它有一個(gè)register()方法。
public function register()
{
$this->booting(function () {
$events = $this->getEvents();
foreach ($events as $event => $listeners) {
foreach (array_unique($listeners) as $listener) {
Event::listen($event, $listener);
}
}
foreach ($this->subscribe as $subscriber) {
Event::subscribe($subscriber);
}
});
}
調(diào)用booting()方法,然后傳遞一個(gè)匿名函數(shù)。那么booting()方法定義于它的父類中。
它的父類是Illuminate\Support\ServiceProvider
public function booting(Closure $callback)
{
$this->bootingCallbacks[] = $callback;
}
把上面的匿名函數(shù),注冊到$this->bootingCallbacks 中。
事件注冊流程分析
事件系統(tǒng),可以通過外觀類Event來調(diào)用。
use Illuminate\Support\Facades\Event;
操作方法是在 App\Providers\EventServiceProvider類中,操作$listen屬性,或者是在boot()方法中,使用Event::listen()方法注冊事件。
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use App\Events\Kindle;
use App\Listeners\JujuListener;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
Kindle::class=>[JujuListener::class]
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
Event::listen(function(){
});
}
}
注冊完畢后,在控制器中引入事件類,然后使用event()全局函數(shù),將事件對應(yīng)作為參數(shù)傳入其中。
use App\Events\Kindle;
public function indexAction()
{
event(new Kindle());
}
event()函數(shù)定義在:Illuminate\Foundation\helpers.php文件中
function event(...$args)
{
return app('events')->dispatch(...$args);
}
因此我們將從dispatcher(事件類) 中的 dispatch()方法,做為入口,進(jìn)行流程分析。
1 dispatch()方法分析
作用:啟動(dòng)事件并呼叫聽眾