目次
イベントシステム
イベント システムのソース コード実装を分析するために、公式ドキュメントに記載されている例を引き続き使用しています。イベントとリスナーを登録するには 2 つの方法があります。
Service
ホームページ バックエンド開発 PHPチュートリアル Laravelイベントシステムの解釈

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

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

この記事では主に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<div class="code" style="position:relative; padding:0px; margin:0px;"><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><div class="contentsignin">ログイン後にコピー</div></div>

Illuminate\Events\Dispatcher

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

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

App\Providers\EventServiceProvider

すべてのイベント リスナーを登録するために、すべてのイベント (キー) とイベントに対応するリスナー (値) を含む listen 配列があり、次に従って柔軟に構成できます。イベントを追加します。 <div class="code" style="position:relative; padding:0px; margin:0px;"><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><div class="contentsignin">ログイン後にコピー</div></div>イベントベースのクロージャを

App\Providers\EventServiceProvider

クラスの boot メソッドに登録することもできます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><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><div class="contentsignin">ログイン後にコピー</div></div>

\App\Providers\EventProvider

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

\Illuminate\Foundation\Bootstrap\BootProviders

を通じてすべてのプロバイダーの ブートを呼び出すと述べました これらのサービスを開始するメソッド。これにより、Laravel アプリケーションでのイベントとリスナーの登録は、\Illuminate\Foundation\Support\Providers\EventServiceProvide クラスの boot メソッドで行われます。見てください: <div class="code" style="position:relative; padding:0px; margin:0px;"><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><div class="contentsignin">ログイン後にコピー</div></div> イベント システムは、

events

サービスのリスニング メソッドとサブスクリプション メソッドを通じて開始され、システム内にイベント、対応するリスナー、およびイベント サブスクライバーを作成することがわかります。 <div class="code" style="position:relative; padding:0px; margin:0px;"><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><div class="contentsignin">ログイン後にコピー</div></div>ワイルドカードを含むイベント名は、

wildcards

配列に均一に配置されます。makeListener は、イベントに対応する listener を作成するために使用されます。 :<div class="code" style="position:relative; padding:0px; margin:0px;"><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><div class="contentsignin">ログイン後にコピー</div></div>

listener

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

makeListener

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

createClassListener

<div class="code" style="position:relative; padding:0px; margin:0px;"><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><div class="contentsignin">ログイン後にコピー</div></div> を通じて引き続き作成されます。リスニング クラスの文字列を通じてリスナーを作成する場合は、クロージャも返されます。 , 現在のリスニング クラスがキュー タスクを実行する場合、返されたクロージャは実行後にタスクをキューにプッシュします。通常のリスニング クラスの場合、返されたクロージャはリスニング オブジェクトを作成し、オブジェクトのハンドルメソッド。したがって、リスナーはイベントが登録されるときにコンテキストをラップするためにクロージャを返し、イベントがトリガーされるのを待つときにクロージャを呼び出してタスクを実行します。

リスナーが作成されると、対応するイベント名をキーとして 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 までご連絡ください。

ホット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ヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

クロスサイトリクエストフォーファリー(CSRF)とは何ですか?また、PHPにCSRF保護をどのように実装しますか? クロスサイトリクエストフォーファリー(CSRF)とは何ですか?また、PHPにCSRF保護をどのように実装しますか? Apr 07, 2025 am 12:02 AM

PHPでは、予測不可能なトークンを使用して、CSRF攻撃を効果的に防ぐことができます。特定の方法には次のものが含まれます。1。フォームのCSRFトークンを生成および埋め込みます。 2.リクエストを処理するときにトークンの有効性を確認します。

PHPで厳密なタイプ(declare(strict_types = 1);)を説明します。 PHPで厳密なタイプ(declare(strict_types = 1);)を説明します。 Apr 07, 2025 am 12:05 AM

PHPの厳格なタイプは、declare(strict_types = 1)を追加することで有効になります。ファイルの上部に。 1)関数パラメーターのタイプチェックと戻り値を強制して、暗黙の型変換を防ぎます。 2)厳格なタイプを使用すると、コードの信頼性と予測可能性を改善し、バグを減らし、保守性と読みやすさを向上させることができます。

どのようにしてクラスが拡張されたり、PHPでメソッドがオーバーライドされたりするのを防ぐことができますか? (最終キーワード) どのようにしてクラスが拡張されたり、PHPでメソッドがオーバーライドされたりするのを防ぐことができますか? (最終キーワード) Apr 08, 2025 am 12:03 AM

PHPでは、最終的なキーワードを使用して、クラスが継承されないようにし、メソッドが上書きされます。 1)クラスを決勝としてマークする場合、クラスを継承することはできません。 2)メソッドを最終的にマークする場合、メソッドはサブクラスによって書き換えられません。最終的なキーワードを使用すると、コードの安定性とセキュリティが保証されます。

PHPの未来:適応と革新 PHPの未来:適応と革新 Apr 11, 2025 am 12:01 AM

PHPの将来は、新しいテクノロジーの傾向に適応し、革新的な機能を導入することで達成されます。1)クラウドコンピューティング、コンテナ化、マイクロサービスアーキテクチャに適応し、DockerとKubernetesをサポートします。 2)パフォーマンスとデータ処理の効率を改善するために、JITコンパイラと列挙タイプを導入します。 3)パフォーマンスを継続的に最適化し、ベストプラクティスを促進します。

バングラ部分モデル検索のlaravelEloquent orm) バングラ部分モデル検索のlaravelEloquent orm) Apr 08, 2025 pm 02:06 PM

LaravelEloquentモデルの検索:データベースデータを簡単に取得するEloquentormは、データベースを操作するための簡潔で理解しやすい方法を提供します。この記事では、さまざまな雄弁なモデル検索手法を詳細に紹介して、データベースからのデータを効率的に取得するのに役立ちます。 1.すべてのレコードを取得します。 ALL()メソッドを使用して、データベーステーブルですべてのレコードを取得します:useapp \ models \ post; $ post = post :: all();これにより、コレクションが返されます。 Foreach Loopまたはその他の収集方法を使用してデータにアクセスできます。

Laravelの地理空間:インタラクティブマップと大量のデータの最適化 Laravelの地理空間:インタラクティブマップと大量のデータの最適化 Apr 08, 2025 pm 12:24 PM

700万のレコードを効率的に処理し、地理空間技術を使用したインタラクティブマップを作成します。この記事では、LaravelとMySQLを使用して700万を超えるレコードを効率的に処理し、それらをインタラクティブなマップの視覚化に変換する方法について説明します。最初の課題プロジェクトの要件:MySQLデータベースに700万のレコードを使用して貴重な洞察を抽出します。多くの人は最初に言語をプログラミングすることを検討しますが、データベース自体を無視します。ニーズを満たすことができますか?データ移行または構造調​​整は必要ですか? MySQLはこのような大きなデータ負荷に耐えることができますか?予備分析:キーフィルターとプロパティを特定する必要があります。分析後、ソリューションに関連している属性はわずかであることがわかりました。フィルターの実現可能性を確認し、検索を最適化するためにいくつかの制限を設定しました。都市に基づくマップ検索

PHP対Python:違いを理解します PHP対Python:違いを理解します Apr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

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を介して展開され、柔軟性とスケーラビリティを向上させます。

See all articles