摘要:事件驅動編程是圖形用戶界面和其他應用程序例如應用程序中使用的主要范例,用于執行某些操作來響應用戶輸入。我們來看一下事件驅動編程帶來的收益?,F在讓我們看看采用事件驅動編程方法如何實現上述相同的功能。
在這篇文章中我們將了解到什么是“事件驅動編程”以及在Laravel中如何開始構建一個事件驅動應用,同時我們還將看到如何通過事件驅動編程來對應用程序的邏輯進行解耦。
在開始之前,先說明一下這篇文章主要是闡述事件驅動這種編程思維和理念的,所以不會涉及到Laravel Events的方方面面。如果你需要更全面地了解Laravel Events和它的各種用法可以訪問Laravel Events文檔來了解詳細信息。
何為事件驅動編程在我們深入事件驅動應用之前,我們先看一下在維基百科里對事件驅動編程的定義:
事件驅動編程是一種編程模式,其中的程序流由諸如用戶動作(鼠標點擊,按鍵)、傳感器輸出或來自其他程序/線程的消息等事件來決定確定。事件驅動編程是圖形用戶界面和其他應用程序(例如JavaScript Web應用程序)中使用的主要范例,用于執行某些操作來響應用戶輸入。
事件驅動應用程序會響應用戶的動作,然后執行對應的代碼來響應用戶的動作。
Laravel Events通過上面的定義,事件是發生在應用程序中的動作。Javascript的事件是像鼠標點擊、鼠標懸浮、按下鍵盤這樣的用戶動作。在Laravel中事件是發生在應用程序中的動作,像郵件通知、記錄日志、用戶注冊、CRUD操作等。Laravel Events系統提供了簡易的觀察者模式實現,讓開發者能夠訂閱和監聽發生在應用中的動作。
應用中有些事件是由Laravel框架自動發起。比如說當使用Eloquent Model執行create、save、update或者delete操作時Laravel將分別發起created、saved、updated、和deleted事件。如果需要的話我們可以監聽這些事件從而執行相應的代碼來完成自己的需求。除了Laravel框架自動發起的事件,我們還可以根據自己應用的需要讓Laravel發起我們自己定義的事件。比如說你可以發起一個userRegistered事件,在事件處理程序中發送用戶驗證郵件好讓新注冊的用戶能夠驗證自己的郵箱。
發起一個事件并不會讓應用程序執行任何相應的操作,我們必須在事件處理程序中對被發起的事件進行相應地回應。Laravel Events由兩部分組成Event Handler和Event Listener。Event Handler中包含了發起事件相關的信息。Event Listener監聽事件對象并對事件進行回應,Event Listener是我們實現事件邏輯的地方。在Laravel中Event類文件被存放在app/Events目錄,Listener類文件被存放在app/Listeners目錄。
為何使用事件驅動編程我們已經了解事件驅動應用和Laravel Events的概念了,你可能會好奇為什么要采用事件驅動這種方法來構建你的應用程序。我們來看一下事件驅動編程帶來的收益。
首先,事件是一種解耦應用程序各個方面的好方法,因為單個事件可以有多個不依賴于彼此的監聽器。通過解耦,不會因為你使用了不適合域邏輯的代碼而污染了代碼庫。其次,由于應用程序是松散耦合的,你可以輕松擴展應用程序的功能,而不必打亂/重寫應用程序或應用程序的某些其他功能。
應用示例現在假設新用戶注冊了我們的應用程序后,應用程序會給用戶發送一封歡迎郵件,同時會自動給用戶訂閱應用上的每周新聞簡報。在不應用事件驅動方式的情況下代碼往往是如下這樣:
// without event-driven approach public function register(Request $request) { // validate input $this->validate($request->all(), [ "name" => "required", "email" => "required|unique:users", "password" => "required|min:6|confirmed", ]); // create user and persist in database $user = $this->create($request->all()); // send welcome email Mail::to($user)->send(new WelcomeToSiteName($user)); // Sign user up for weekly newsletter Newsletter::subscribe($user->email, [ "FNAME": $user->fname, "LNAME": $user->lname ], "SiteName Weekly"); // login newly registered user $this->guard()->login($user); return redirect("/home"); }
你可以看到發送歡迎郵件和訂閱新聞簡報的邏輯緊密耦合到了register方法里, 根據關注點分離原則,register方法不應該關心發送歡迎郵件和訂閱新聞簡報的具體實現。你可能會覺得發送歡迎郵件和訂閱新聞放到register方法里也沒什么,但是如果在注冊時除了發送郵件還要給用戶發送短信呢?繼續寫在register方法里:
public function register(Request $request) { // validate input // create user and persist in database // send welcome email Mail::to($user)->send(new WelcomeToSiteName($user)); // send SMS Nexmo::message()->send([ "to" => $user->phone_number, "from" => "SiteName", "text" => "Welcome and thanks for signup on SiteName." ]); // Sign user up for weekly newsletter Newsletter::subscribe($user->email, [ "FNAME": $user->fname, "LNAME": $user->lname ], "SiteName Weekly"); // login newly registered user return redirect("/home"); }
可以看到代碼庫開始變得臃腫?,F在讓我們看看采用事件驅動編程方法如何實現上述相同的功能。
// with event-driven approach public function register(Request $request) { // validate input $this->validate($request->all(), [ "name" => "required", "email" => "required|unique:users", "password" => "required|min:6|confirmed", ]); // create user and persist in database $user = $this->create($request->all()); // fire event once user has been created event(new UserRegistered($user)); // login newly registered user $this->guard()->login($user); return redirect("/home"); }
一旦創建了用戶,UserRegistered事件就會被觸發?;叵胍幌?,我們之前提到,發起一個事件后應用并不會自己做任何事情,我們需要監聽UserRegistered事件并執行必要的操作。讓我們創建UserRegistered事件類和SendWelcomeMail以及SignupForWeeklyNewsletter監聽器類:
php artisan make:event UserRegistered php artisan make:listener SendWelcomeMail --event=UserRegistered php artisan make:listener SignupForWeeklyNewsletter --event=UserRegistered
事件和監聽器之間的對應關系需要注冊到EventServiceProvider的$listen屬性里:
protected $listen = [ UserRegistered::class => [ SendWelcomeMail::class, SignupForWeeklyNewsletter::class, ], ];
打開app/Events/UserRegistered.php文件更新它的構造方法:
public $user; public function __construct(User $user) { $this->user = $user; }
聲明$user為public,它將被傳遞給監聽器,而監聽器可以用它來執行必要的邏輯。接下來,事件監聽器將在其handle方法中接收到事件實例。在handle方法中,我們可以執行響應事件的操作。
// app/Listeners/SendWelcomeMail.php public function handle(UserRegistered $event) { // send welcome email Mail::to($event->user)->send(new WelcomeToSiteName($event->user)); } // app/Listeners/SignupForWeeklyNewsletter.php public function handle(UserRegistered $event) { // Sign user up for weekly newsletter Newsletter::subscribe($event->user->email, [ "FNAME": $event->user->fname, "LNAME": $event->user->lname ], "SiteName Weekly"); }
可以看到通過事件驅動的方式我們讓register方法的代碼盡可能的少并且專注于用戶注冊這件事上,其它的邏輯由UserRegistered事件的監聽器來負責,現在如果說我們想在用戶注冊后發送短信給新注冊的用戶,我們所要做的就是創建一個新的事件監聽器來監聽UserRegistered事件何時被觸發
php artisan make:listener SendWelcomeSMS --event=UserRegistered // app/Listeners/SendWelcomeSMS.php public function handle(UserRegistered $event) { // send SMS Nexmo::message()->send([ "to" => $event->user->phone_number, "from" => "SiteName", "text" => "Welcome and thanks for signup on SiteName." ]); }
注:記得要更新EventServiceProvider里的$listen屬性
Conclusion在這篇文章中,我們已經能夠理解事件驅動的編程是什么,事件驅動的應用程序是什么以及Laravel事件是什么。我們還研究了事件驅動應用程序的優勢。但是,像跟所有有積極影響的編程概念一樣,它也有缺點。事件驅動型應用程序的主要缺點是讓程序流變得復雜了,尤其一些剛接觸開發的人可能很難真正理解應用程序的流程。以上面的實現為例,通過register方法我們并不能直觀地看到程序在創建用戶后會向新用戶發送一封歡迎郵件,并將其注冊到新聞通訊中。
所以在開發中應該根據場景創造性地使用它,利用它的優勢為你的應用程序解耦,而不是過度使用它。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/28430.html
摘要:前言年底了不太忙,最近一段時間也一直在研究,就想寫篇關于比較深一點的教程系列啥的,于是就找到站長給開了寫教程的渠道。優點的就是為藝術家創造的框架,它也是工程化的趨勢。項目維護方便也是事實。如果有遇到問題可以直接在教程下面留言。 前言 年底了不太忙,最近一段時間也一直在研究laravel,就想寫篇關于laravel比較深一點的教程系列啥的,于是就找到站長給開了寫教程的渠道。由于第一次寫,...
摘要:初步嘗試既然最常見的注冊命令的方式是修改類中的,那么一般正常人都會從這邊開始下手。又要自己取出實例,又要自己調用方法,調用方法之前還有自己先把實例化這么繁瑣,肯定不是運行時添加命令的最佳實踐,所以我決定繼續尋找更優解。 本文首發于我的博客,原文鏈接:https://blessing.studio/best-... 雖然 Laravel 官方文檔提供的添加 Artisan Command...
摘要:上例的功能塊定義了如下節點樹入口節點是面板,結合該節點的函數書寫特點,我們接著介紹最佳實踐如何處理功能塊之內的編程。 本文介紹 React + Shadow Widget 應用于通用 GUI 開發的最佳實踐,只聚焦于典型場景下最優開發方法。分上、下兩篇講解,上篇概述最佳實踐,介紹功能塊劃分。 showImg(https://segmentfault.com/img/bVWu3d?w=6...
摘要:編程書籍的整理和收集最近一直在學習深度學習和機器學習的東西,發現深入地去學習就需要不斷的去提高自己算法和高數的能力然后也找了很多的書和文章,隨著不斷的學習,也整理了下自己的學習筆記準備分享出來給大家后續的文章和總結會繼續分享,先分享一部分的 編程書籍的整理和收集 最近一直在學習deep learning深度學習和機器學習的東西,發現深入地去學習就需要不斷的去提高自己算法和高數的能力然后...
閱讀 1583·2021-09-24 10:38
閱讀 1518·2021-09-22 15:15
閱讀 3066·2021-09-09 09:33
閱讀 910·2019-08-30 11:08
閱讀 645·2019-08-30 10:52
閱讀 1258·2019-08-30 10:52
閱讀 2351·2019-08-28 18:01
閱讀 529·2019-08-28 17:55