検索

Laravelイベントシステムの解釈

Jul 06, 2018 pm 02:23 PM
laravelphpソースコード分析

この記事では主にLaravelのイベントシステムの解釈を紹介しますが、これは参考になると思いますので、皆さんにもシェアしておきますので、困っている方は参考にしてください

イベントシステム

Laravelのイベントが提供するものアプリケーション内で発生するさまざまなイベントをサブスクライブしてリッスンできる単純なオブザーバーの実装。イベントには互いに独立した複数のリスナーを含めることができるため、イベント メカニズムはアプリケーションを分離する良い方法です。 laravel のイベント システムは 2 つの部分で構成されています。1 つはイベントの名前です。イベントの名前は、event.email などの文字列にすることも、次のような文字列にすることもできます。 App\Events\OrderShipped などのイベント クラス; もう 1 つはイベント リスナー listener で、クロージャまたはリスニング クラス (App\Listeners など) にすることができます。 \Send ShippingNotification

イベント システムのソース コード実装を分析するために、引き続き公式ドキュメントに記載されている例を使用しますが、アプリケーションがイベントとリスナーを登録する前に、Laravel はアプリケーションの起動時に最初にイベント処理を登録します。 ##イベントサービス。

Laravel登録イベントサービス

Laravelアプリケーション作成時に登録される基本サービスの中に、

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));
    }
}

EventServiceProvider#があります。 ## は /Illuminate/Events/EventServiceProvider<pre class='brush:php;toolbar:false;'>public function register() { $this-&gt;app-&gt;singleton(&amp;#39;events&amp;#39;, function ($app) { return (new Dispatcher($app))-&gt;setQueueResolver(function () use ($app) { return $app-&gt;make(QueueFactoryContract::class); }); }); }</pre>

Illuminate\Events\Dispatcher

events サービスの実際の実装クラスであり、Event ファサードは events サービスの静的プロキシであり、イベント システム関連のメソッドは Illuminate\Events\Dispatcher によって提供されます。 アプリケーションでのイベントの登録と監視

イベント システムのソース コード実装を分析するために、公式ドキュメントに記載されている例を引き続き使用しています。イベントとリスナーを登録するには 2 つの方法があります。

App\Providers\EventServiceProvider

すべてのイベント リスナーを登録するために、すべてのイベント (キー) とイベントに対応するリスナー (値) を含む listen 配列があり、次に従って柔軟に構成できます。イベントを追加します。 <pre class='brush:php;toolbar:false;'>/** * 应用程序的事件监听器映射。 * * @var array */ protected $listen = [ &amp;#39;App\Events\OrderShipped&amp;#39; =&gt; [ &amp;#39;App\Listeners\SendShipmentNotification&amp;#39;, ], ];</pre>イベントベースのクロージャを

App\Providers\EventServiceProvider

クラスの boot メソッドに登録することもできます。 <pre class='brush:php;toolbar:false;'>/** * 注册应用程序中的任何其他事件。 * * @return void */ public function boot() { parent::boot(); Event::listen(&amp;#39;event.name&amp;#39;, function ($foo, $bar) { // }); }</pre>

\App\Providers\EventProvider

クラスの主なジョブは、アプリケーションにイベントを登録することです。この登録クラスの主な機能は、イベント システムを開始することです。このクラスは \Illuminate\Foundation\Support\Providers\EventServiceProvide を継承します。 サービスプロバイダーを追加したときに、すべてのサービスを登録した後、Laravel アプリケーションは

\Illuminate\Foundation\Bootstrap\BootProviders

を通じてすべてのプロバイダーの ブートを呼び出すと述べました これらのサービスを開始するメソッド。これにより、Laravel アプリケーションでのイベントとリスナーの登録は、\Illuminate\Foundation\Support\Providers\EventServiceProvide クラスの boot メソッドで行われます。見てください: <pre class='brush:php;toolbar:false;'>public function boot() { foreach ($this-&gt;listens() as $event =&gt; $listeners) { foreach ($listeners as $listener) { Event::listen($event, $listener); } } foreach ($this-&gt;subscribe as $subscriber) { Event::subscribe($subscriber); } }</pre> イベント システムは、

events

サービスのリスニング メソッドとサブスクリプション メソッドを通じて開始され、システム内にイベント、対応するリスナー、およびイベント サブスクライバーを作成することがわかります。 <pre class='brush:php;toolbar:false;'>namespace Illuminate\Events; class Dispatcher implements DispatcherContract { public function listen($events, $listener) { foreach ((array) $events as $event) { if (Str::contains($event, &amp;#39;*&amp;#39;)) { $this-&gt;setupWildcardListen($event, $listener); } else { $this-&gt;listeners[$event][] = $this-&gt;makeListener($listener); } } } protected function setupWildcardListen($event, $listener) { $this-&gt;wildcards[$event][] = $this-&gt;makeListener($listener, true); } }</pre>ワイルドカードを含むイベント名は、

wildcards

配列に均一に配置されます。makeListener は、イベントに対応する listener を作成するために使用されます。 :<pre class='brush:php;toolbar:false;'>class Dispatcher implements DispatcherContract { public function makeListener($listener, $wildcard = false) { if (is_string($listener)) {//如果是监听器是类,去创建监听类 return $this-&gt;createClassListener($listener, $wildcard); } return function ($event, $payload) use ($listener, $wildcard) { if ($wildcard) { return $listener($event, $payload); } else { return $listener(...array_values($payload)); } }; } }</pre>

listener

を作成する際に、リスニングオブジェクトがリスニングクラスであるかクロージャ関数であるかを判定します。 クロージャ リスニングの場合、

makeListener

は別のレイヤーをラップし、イベント リスナーとしてクロージャ関数を返します。 リスニング クラスの場合、リスナーは

createClassListener

<pre class='brush:php;toolbar:false;'>class Dispatcher implements DispatcherContract { public function createClassListener($listener, $wildcard = false) { return function ($event, $payload) use ($listener, $wildcard) { if ($wildcard) { return call_user_func($this-&gt;createClassCallable($listener), $event, $payload); } else { return call_user_func_array( $this-&gt;createClassCallable($listener), $payload ); } }; } protected function createClassCallable($listener) { list($class, $method) = $this-&gt;parseClassCallable($listener); if ($this-&gt;handlerShouldBeQueued($class)) { //如果当前监听类是队列的话,会将任务推送给队列 return $this-&gt;createQueuedHandlerCallable($class, $method); } else { return [$this-&gt;container-&gt;make($class), $method]; } } }</pre> を通じて引き続き作成されます。リスニング クラスの文字列を通じてリスナーを作成する場合は、クロージャも返されます。 , 現在のリスニング クラスがキュー タスクを実行する場合、返されたクロージャは実行後にタスクをキューにプッシュします。通常のリスニング クラスの場合、返されたクロージャはリスニング オブジェクトを作成し、オブジェクトのハンドルメソッド。したがって、リスナーはイベントが登録されるときにコンテキストをラップするためにクロージャを返し、イベントがトリガーされるのを待つときにクロージャを呼び出してタスクを実行します。

リスナーが作成されると、対応するイベント名をキーとして listener 配列に配置されます。配列はに対応します。前にオブザーバーパターンについて説明したときの

Subject

クラスの observers 配列と同じように、配列内に複数の listener を含めることができますが、Laravelはそれよりも複雑です。その listener 配列は、複数の Subject と対応する Observer の間の対応する関係を記録します。 イベントのトリガーイベント名またはイベント クラスを使用してイベントをトリガーできます。イベントをトリガーするときは、Event::fire(new OrdershipmentNotification) を使用します。

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;
}

からも来ます。イベントがトリガーされると、イベント名に対応するすべての listener クロージャーが listeners から見つかります。以前に登録されたイベントによって生成されます。これらのクロージャは、リスナーでタスクを実行するために呼び出されます。注意する必要があるのは:

  • イベント名パラメータがイベント オブジェクトの場合、イベント オブジェクトのクラス名がイベント名として使用され、それ自体が時間パラメータとしてリスナーに渡されます。

  • イベントのトリガー時に halt パラメーターが渡された場合、リスナーが非 false を返した後、イベントは残りのリスナーに伝播し続けません。それ以外の場合は、すべてのリスナーが実行された後、リスナーの戻り値が一律に配列として返されます。

  • リスナーがブール値 false を返した場合、イベントは残りのリスナーへの伝播を直ちに停止します。

Laravel のイベント システムの原理は、前述のオブザーバー パターンと同じですが、フレームワークの作成者は非常に熟練しており、クロージャを巧みに組み合わせて適用してイベント システムを実装しています。キュー処理を必要とするイベントの場合と同様に、アプリケーション イベントは、関心の分散の原則を使用して、より複雑なビジネス シナリオでアプリケーション内のコード ロジックを効果的に分離できます。もちろん、アプリケーション イベントは、すべての状況でコードを記述するのに適しているわけではありません。以前、イベント駆動プログラミングに関するイベントの適用シナリオを説明する記事を書きましたので、興味があれば読んでください。

上記がこの記事の全内容です。皆様の学習に少しでもお役に立てれば幸いです。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

関連推奨事項:

Laravel ユーザー認証システム (基本入門)

Laravel5.5 以降のマルチ環境。環境設定の読み取り

以上がLaravelイベントシステムの解釈の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
PHPの現在のステータス:Web開発動向を見てくださいPHPの現在のステータス:Web開発動向を見てくださいApr 13, 2025 am 12:20 AM

PHPは、現代のWeb開発、特にコンテンツ管理とeコマースプラットフォームで依然として重要です。 1)PHPには、LaravelやSymfonyなどの豊富なエコシステムと強力なフレームワークサポートがあります。 2)パフォーマンスの最適化は、Opcacheとnginxを通じて達成できます。 3)PHP8.0は、パフォーマンスを改善するためにJITコンパイラを導入します。 4)クラウドネイティブアプリケーションは、DockerおよびKubernetesを介して展開され、柔軟性とスケーラビリティを向上させます。

PHP対その他の言語:比較PHP対その他の言語:比較Apr 13, 2025 am 12:19 AM

PHPは、特に迅速な開発や動的なコンテンツの処理に適していますが、データサイエンスとエンタープライズレベルのアプリケーションには良くありません。 Pythonと比較して、PHPはWeb開発においてより多くの利点がありますが、データサイエンスの分野ではPythonほど良くありません。 Javaと比較して、PHPはエンタープライズレベルのアプリケーションでより悪化しますが、Web開発により柔軟性があります。 JavaScriptと比較して、PHPはバックエンド開発により簡潔ですが、フロントエンド開発のJavaScriptほど良くありません。

PHP対Python:コア機能と機能PHP対Python:コア機能と機能Apr 13, 2025 am 12:16 AM

PHPとPythonにはそれぞれ独自の利点があり、さまざまなシナリオに適しています。 1.PHPはWeb開発に適しており、組み込みのWebサーバーとRich Functionライブラリを提供します。 2。Pythonは、簡潔な構文と強力な標準ライブラリを備えたデータサイエンスと機械学習に適しています。選択するときは、プロジェクトの要件に基づいて決定する必要があります。

PHP:Web開発の重要な言語PHP:Web開発の重要な言語Apr 13, 2025 am 12:08 AM

PHPは、サーバー側で広く使用されているスクリプト言語で、特にWeb開発に適しています。 1.PHPは、HTMLを埋め込み、HTTP要求と応答を処理し、さまざまなデータベースをサポートできます。 2.PHPは、ダイナミックWebコンテンツ、プロセスフォームデータ、アクセスデータベースなどを生成するために使用され、強力なコミュニティサポートとオープンソースリソースを備えています。 3。PHPは解釈された言語であり、実行プロセスには語彙分析、文法分析、編集、実行が含まれます。 4.PHPは、ユーザー登録システムなどの高度なアプリケーションについてMySQLと組み合わせることができます。 5。PHPをデバッグするときは、error_reporting()やvar_dump()などの関数を使用できます。 6. PHPコードを最適化して、キャッシュメカニズムを使用し、データベースクエリを最適化し、組み込み関数を使用します。 7

PHP:多くのウェブサイトの基礎PHP:多くのウェブサイトの基礎Apr 13, 2025 am 12:07 AM

PHPが多くのWebサイトよりも優先テクノロジースタックである理由には、その使いやすさ、強力なコミュニティサポート、広範な使用が含まれます。 1)初心者に適した学習と使用が簡単です。 2)巨大な開発者コミュニティと豊富なリソースを持っています。 3)WordPress、Drupal、その他のプラットフォームで広く使用されています。 4)Webサーバーとしっかりと統合して、開発の展開を簡素化します。

誇大広告を超えて:今日のPHPの役割の評価誇大広告を超えて:今日のPHPの役割の評価Apr 12, 2025 am 12:17 AM

PHPは、特にWeb開発の分野で、最新のプログラミングで強力で広く使用されているツールのままです。 1)PHPは使いやすく、データベースとシームレスに統合されており、多くの開発者にとって最初の選択肢です。 2)動的コンテンツ生成とオブジェクト指向プログラミングをサポートし、Webサイトを迅速に作成および保守するのに適しています。 3)PHPのパフォーマンスは、データベースクエリをキャッシュおよび最適化することで改善でき、その広範なコミュニティと豊富なエコシステムにより、今日のテクノロジースタックでは依然として重要になります。

PHPの弱い参照は何ですか、そしていつ有用ですか?PHPの弱い参照は何ですか、そしていつ有用ですか?Apr 12, 2025 am 12:13 AM

PHPでは、弱い参照クラスを通じて弱い参照が実装され、ガベージコレクターがオブジェクトの回収を妨げません。弱い参照は、キャッシュシステムやイベントリスナーなどのシナリオに適しています。オブジェクトの生存を保証することはできず、ごみ収集が遅れる可能性があることに注意する必要があります。

PHPで__invoke Magicメソッドを説明してください。PHPで__invoke Magicメソッドを説明してください。Apr 12, 2025 am 12:07 AM

\ _ \ _ Invokeメソッドを使用すると、オブジェクトを関数のように呼び出すことができます。 1。オブジェクトを呼び出すことができるように\ _ \ _呼び出しメソッドを定義します。 2。$ obj(...)構文を使用すると、PHPは\ _ \ _ Invokeメソッドを実行します。 3。ロギングや計算機、コードの柔軟性の向上、読みやすさなどのシナリオに適しています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール