Table of Contents
Event system
Laravel registration event service
Registering events and monitoring in applications
Trigger event
Home Backend Development PHP Tutorial Interpretation of Laravel event system

Interpretation of Laravel event system

Jul 06, 2018 pm 02:23 PM
laravel php Source code analysis

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.eventsService.

Laravel registration event service

Among the basic services registered when the Laravel application is created, there is Eventservice

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));
    }
}
Copy after login

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);
        });
    });
}
Copy after login

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',
    ],
];
Copy after login

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) {
        //
    });
}
Copy after login

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);
    }
}
Copy after login

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);
    }
}
Copy after login

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));
            }
        };
    }
}
Copy after login

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];
        }
    }
}
Copy after login

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 eventsService

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;
}
Copy after login

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!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

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

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1657
14
PHP Tutorial
1257
29
C# Tutorial
1229
24
Laravel Introduction Example Laravel Introduction Example Apr 18, 2025 pm 12:45 PM

Laravel is a PHP framework for easy building of web applications. It provides a range of powerful features including: Installation: Install the Laravel CLI globally with Composer and create applications in the project directory. Routing: Define the relationship between the URL and the handler in routes/web.php. View: Create a view in resources/views to render the application's interface. Database Integration: Provides out-of-the-box integration with databases such as MySQL and uses migration to create and modify tables. Model and Controller: The model represents the database entity and the controller processes HTTP requests.

Solve caching issues in Craft CMS: Using wiejeben/craft-laravel-mix plug-in Solve caching issues in Craft CMS: Using wiejeben/craft-laravel-mix plug-in Apr 18, 2025 am 09:24 AM

When developing websites using CraftCMS, you often encounter resource file caching problems, especially when you frequently update CSS and JavaScript files, old versions of files may still be cached by the browser, causing users to not see the latest changes in time. This problem not only affects the user experience, but also increases the difficulty of development and debugging. Recently, I encountered similar troubles in my project, and after some exploration, I found the plugin wiejeben/craft-laravel-mix, which perfectly solved my caching problem.

Laravel user login function Laravel user login function Apr 18, 2025 pm 12:48 PM

Laravel provides a comprehensive Auth framework for implementing user login functions, including: Defining user models (Eloquent model), creating login forms (Blade template engine), writing login controllers (inheriting Auth\LoginController), verifying login requests (Auth::attempt) Redirecting after login is successful (redirect) considering security factors: hash passwords, anti-CSRF protection, rate limiting and security headers. In addition, the Auth framework also provides functions such as resetting passwords, registering and verifying emails. For details, please refer to the Laravel documentation: https://laravel.com/doc

The Continued Use of PHP: Reasons for Its Endurance The Continued Use of PHP: Reasons for Its Endurance Apr 19, 2025 am 12:23 AM

What’s still popular is the ease of use, flexibility and a strong ecosystem. 1) Ease of use and simple syntax make it the first choice for beginners. 2) Closely integrated with web development, excellent interaction with HTTP requests and database. 3) The huge ecosystem provides a wealth of tools and libraries. 4) Active community and open source nature adapts them to new needs and technology trends.

Laravel framework installation method Laravel framework installation method Apr 18, 2025 pm 12:54 PM

Article summary: This article provides detailed step-by-step instructions to guide readers on how to easily install the Laravel framework. Laravel is a powerful PHP framework that speeds up the development process of web applications. This tutorial covers the installation process from system requirements to configuring databases and setting up routing. By following these steps, readers can quickly and efficiently lay a solid foundation for their Laravel project.

How to learn Laravel How to learn Laravel for free How to learn Laravel How to learn Laravel for free Apr 18, 2025 pm 12:51 PM

Want to learn the Laravel framework, but suffer from no resources or economic pressure? This article provides you with free learning of Laravel, teaching you how to use resources such as online platforms, documents and community forums to lay a solid foundation for your PHP development journey from getting started to master.

How to view the version number of laravel? How to view the version number of laravel How to view the version number of laravel? How to view the version number of laravel Apr 18, 2025 pm 01:00 PM

The Laravel framework has built-in methods to easily view its version number to meet the different needs of developers. This article will explore these methods, including using the Composer command line tool, accessing .env files, or obtaining version information through PHP code. These methods are essential for maintaining and managing versioning of Laravel applications.

What versions of laravel are there? How to choose the version of laravel for beginners What versions of laravel are there? How to choose the version of laravel for beginners Apr 18, 2025 pm 01:03 PM

In the Laravel framework version selection guide for beginners, this article dives into the version differences of Laravel, designed to assist beginners in making informed choices among many versions. We will focus on the key features of each release, compare their pros and cons, and provide useful advice to help beginners choose the most suitable version of Laravel based on their skill level and project requirements. For beginners, choosing a suitable version of Laravel is crucial because it can significantly impact their learning curve and overall development experience.

See all articles