Interpretation of Laravel event system
This article mainly introduces the interpretation of Laravel event system, which has certain reference value. Now I share it with everyone. Friends in need can refer to
Event system
Laravel's Events provides a simple observer implementation that can subscribe to and listen to various events that occur in the application. The event mechanism is a good way to decouple applications, because an event can have multiple listeners that are independent of each other. The event system in laravel
consists of two parts. One is the name of the event. The name of the event can be a string, such as event.email
, or it can be an event class, such as App\Events\OrderShipped
; The other is the event listener listener
, which can be a closure or a listening class, such as App\Listeners\SendShipmentNotification
.
We still use the example given in the official documentation to analyze the source code implementation of the event system. However, before the application registers events and listeners, Laravel will first register the event processing when the application starts.events
Service.
Laravel registration event service
Among the basic services registered when the Laravel application is created, there is Event
service
namespace Illuminate\Foundation; class Application extends Container implements ... { public function __construct($basePath = null) { ... $this->registerBaseServiceProviders(); ... } protected function registerBaseServiceProviders() { $this->register(new EventServiceProvider($this)); $this->register(new LogServiceProvider($this)); $this->register(new RoutingServiceProvider($this)); } }
EventServiceProvider
is /Illuminate/Events/EventServiceProvider
public function register() { $this->app->singleton('events', function ($app) { return (new Dispatcher($app))->setQueueResolver(function () use ($app) { return $app->make(QueueFactoryContract::class); }); }); }
Illuminate\Events\Dispatcher
is the real implementation class of events
service, and Event
The facade is a static proxy for the events
service, and event system-related methods are provided by Illuminate\Events\Dispatcher
.
Registering events and monitoring in applications
We still use the example given in the official documentation to analyze the source code implementation of the event system. There are two ways to register events and listeners,App\Providers\EventServiceProvider
There is a listen
array containing all events (keys) and the listeners (values) corresponding to the events to register all event listeners, which can be flexibly configured according to needs. Add event.
/** * 应用程序的事件监听器映射。 * * @var array */ protected $listen = [ 'App\Events\OrderShipped' => [ 'App\Listeners\SendShipmentNotification', ], ];
You can also register event-based closures in the boot
method of the App\Providers\EventServiceProvider
class.
/** * 注册应用程序中的任何其他事件。 * * @return void */ public function boot() { parent::boot(); Event::listen('event.name', function ($foo, $bar) { // }); }
You can see that the main job of the \App\Providers\EventProvider
class is to register events in the application. The main function of this registration class is to start the event system. This class inherits from \Illuminate\Foundation\Support\Providers\EventServiceProvide
.
We said when we added the service provider that after registering all services, the Laravel application will call the boot of all Providers through
\Illuminate\Foundation\Bootstrap\BootProviders
method to start these services, so the registration of events and listeners in Laravel applications occurs in the boot
method of the \Illuminate\Foundation\Support\Providers\EventServiceProvide
class, Let’s take a look:
public function boot() { foreach ($this->listens() as $event => $listeners) { foreach ($listeners as $listener) { Event::listen($event, $listener); } } foreach ($this->subscribe as $subscriber) { Event::subscribe($subscriber); } }
You can see that the event system is started through the listening and subscription methods of the events
service to create events, corresponding listeners, and event subscribers in the system .
namespace Illuminate\Events; class Dispatcher implements DispatcherContract { public function listen($events, $listener) { foreach ((array) $events as $event) { if (Str::contains($event, '*')) { $this->setupWildcardListen($event, $listener); } else { $this->listeners[$event][] = $this->makeListener($listener); } } } protected function setupWildcardListen($event, $listener) { $this->wildcards[$event][] = $this->makeListener($listener, true); } }
Event names containing wildcards will be uniformly put into the wildcards
array. makeListener
is used to create the listener
corresponding to the event. :
class Dispatcher implements DispatcherContract { public function makeListener($listener, $wildcard = false) { if (is_string($listener)) {//如果是监听器是类,去创建监听类 return $this->createClassListener($listener, $wildcard); } return function ($event, $payload) use ($listener, $wildcard) { if ($wildcard) { return $listener($event, $payload); } else { return $listener(...array_values($payload)); } }; } }
When creating listener
, it will be judged whether the listening object is a listening class or a closure function.
For closure listening, makeListener
will wrap another layer and return a closure function as the event listener.
For the listening class, the listener will continue to be created through createClassListener
class Dispatcher implements DispatcherContract { public function createClassListener($listener, $wildcard = false) { return function ($event, $payload) use ($listener, $wildcard) { if ($wildcard) { return call_user_func($this->createClassCallable($listener), $event, $payload); } else { return call_user_func_array( $this->createClassCallable($listener), $payload ); } }; } protected function createClassCallable($listener) { list($class, $method) = $this->parseClassCallable($listener); if ($this->handlerShouldBeQueued($class)) { //如果当前监听类是队列的话,会将任务推送给队列 return $this->createQueuedHandlerCallable($class, $method); } else { return [$this->container->make($class), $method]; } } }
For creating the listener through the string of the listening class, a closure is also returned , if the current listening class is to execute a queue task, the returned closure will push the task to the queue after execution. If it is a normal listening class, the closure returned will make the listening object and execute the of the object. handle
method. Therefore, the listener returns the closure in order to wrap the context when the event is registered, and call the closure to perform the task when waiting for the event to be triggered.
After the listener is created, it will be placed in the array with the corresponding event name as the key in the listener
array. An event name in the listener
array corresponds to There can be multiple listener
in the array, just like the observers
array in the Subject
class when we talked about the observer pattern before, but Laravel is more complicated than that Some, its listener
array will record the corresponding relationship between multiple Subject
and the corresponding Observer
.
Trigger event
You can use the event name or event class to trigger the event. When triggering the event, use Event::fire(new OrdershipmentNotification)
, which also comes from events
Service
public function fire($event, $payload = [], $halt = false) { return $this->dispatch($event, $payload, $halt); } public function dispatch($event, $payload = [], $halt = false) { //如果参数$event事件对象,那么就将对象的类名作为事件名称,对象本身作为携带数据的荷载通过`listener`方法 //的$payload参数的实参传递给listener 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); //如果触发事件时传递了halt参数,并且listener返回了值,那么就不会再去调用事件剩下的listener //否则就将返回值加入到返回值列表中,等所有listener执行完了一并返回 if ($halt && ! is_null($response)) { return $response; } //如果一个listener返回了false, 那么将不会再调用事件剩下的listener if ($response === false) { break; } $responses[] = $response; } return $halt ? null : $responses; } protected function parseEventAndPayload($event, $payload) { if (is_object($event)) { list($payload, $event) = [[$event], get_class($event)]; } return [$event, Arr::wrap($payload)]; } //获取事件名对应的所有listener public function getListeners($eventName) { $listeners = isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : []; $listeners = array_merge( $listeners, $this->getWildcardListeners($eventName) ); return class_exists($eventName, false) ? $this->addInterfaceListeners($eventName, $listeners) : $listeners; }
After the event is triggered, all listener
closures corresponding to the event name will be found from the listeners
generated by the previously registered event. These closures are then called to perform tasks in the listener. What needs to be noted is:
If the event name parameter is an event object, the class name of the event object will be used as the event name, and itself will be passed to the listener as a time parameter.
If the halt parameter is passed when the event is triggered, after the listener returns non-
false
, the event will not continue to propagate to the remaining listeners, otherwise all The return value of the listener will be returned uniformly as an array after all listeners are executed.If a listener returns a Boolean value
false
then the event will immediately stop propagating to the remaining listeners.
The principle of Laravel's event system is still the same as the observer pattern mentioned before, but the author of the framework is very skilled and cleverly combines and applies closures to implement the event system, as well as for For events that require queue processing, application events can use the principle of dispersion of concerns to effectively decouple the code logic in the application in some more complex business scenarios. Of course, application events are not suitable for writing code under all circumstances. I wrote before I have written an article on event-driven programming to explain the application scenarios of events. If you are interested, you can read it.
The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!
Related recommendations:
Laravel User Authentication System (Basic Introduction)
Laravel5.5 and above multi-environment. env configuration reading
The above is the detailed content of Interpretation of Laravel event system. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

PHP and Python each have their own advantages, and choose according to project requirements. 1.PHP is suitable for web development, especially for rapid development and maintenance of websites. 2. Python is suitable for data science, machine learning and artificial intelligence, with concise syntax and suitable for beginners.

PHP remains important in modern web development, especially in content management and e-commerce platforms. 1) PHP has a rich ecosystem and strong framework support, such as Laravel and Symfony. 2) Performance optimization can be achieved through OPcache and Nginx. 3) PHP8.0 introduces JIT compiler to improve performance. 4) Cloud-native applications are deployed through Docker and Kubernetes to improve flexibility and scalability.

PHP is used to build dynamic websites, and its core functions include: 1. Generate dynamic content and generate web pages in real time by connecting with the database; 2. Process user interaction and form submissions, verify inputs and respond to operations; 3. Manage sessions and user authentication to provide a personalized experience; 4. Optimize performance and follow best practices to improve website efficiency and security.

PHP is still dynamic and still occupies an important position in the field of modern programming. 1) PHP's simplicity and powerful community support make it widely used in web development; 2) Its flexibility and stability make it outstanding in handling web forms, database operations and file processing; 3) PHP is constantly evolving and optimizing, suitable for beginners and experienced developers.

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

PHP is widely used in e-commerce, content management systems and API development. 1) E-commerce: used for shopping cart function and payment processing. 2) Content management system: used for dynamic content generation and user management. 3) API development: used for RESTful API development and API security. Through performance optimization and best practices, the efficiency and maintainability of PHP applications are improved.

PHP and Python have their own advantages and disadvantages, and the choice depends on project needs and personal preferences. 1.PHP is suitable for rapid development and maintenance of large-scale web applications. 2. Python dominates the field of data science and machine learning.

The core benefits of PHP include ease of learning, strong web development support, rich libraries and frameworks, high performance and scalability, cross-platform compatibility, and cost-effectiveness. 1) Easy to learn and use, suitable for beginners; 2) Good integration with web servers and supports multiple databases; 3) Have powerful frameworks such as Laravel; 4) High performance can be achieved through optimization; 5) Support multiple operating systems; 6) Open source to reduce development costs.
