laravel生命周期,laravel created_at 時間戳_Laravel 單行為控制器設計的魅力

 2023-10-02 阅读 30 评论 0

摘要:昨天,Jeffrey Way 發布了一條推文,他問大家更愿意將其控制器命名為單數還是復數。 我回答我兩種方案都不選,我使用單動作控制器。隨后發生的是,有的人同意,有的不同意,有的甚至做出了最奇怪的事情。由于十分強烈的反映,我想

昨天,Jeffrey Way 發布了一條推文,他問大家更愿意將其控制器命名為單數還是復數。 我回答我兩種方案都不選,我使用單動作控制器。隨后發生的是,有的人同意,有的不同意,有的甚至做出了最奇怪的事情。

由于十分強烈的反映,我想寫一篇文章來解釋為什么我愛單行為控制器、還有我為什么覺得它們很美妙。

首先在開始文章之前,我想要說這個東西并不是只有單一的真相。與往常一樣,我想指出的是,一切都歸結于你的個人喜好。我只能教、建議和指出一些事情,由你來決定是否同意、不同意、接受、學習和 / 或調整。或者都不是。從這篇博客中獲得你想要的,隨心所欲地做讓自己感到舒適的事情吧。

對比 CRUD 和 Domain Modelling

laravel生命周期?開始前,我們先來想想我們傾向于寫 resourceful 的 CRUD 控制器。我相信很多人會堅持使用這種做法,因為這是 Laravel 中的一個標準做法,文檔中的大多數示例也是使用這種方法。另外,這或許也是你在各類博客或 app 代碼中經常看到的。

但是,如果你停下來思考一下,這是編寫它們的最佳方法嗎?是軟件行業的一般性做法嗎?最近幾年,我在 “領域驅動設計”(Domain Driven Design) 等領域投入了大量時間,并且思考軟件如何應用于你工作的領域(Domian)以及它轉化的過程。當您開始考慮模仿您領域中無處不在的語言的術語和措辭時,您會發現您的代碼將變得更加清晰明了,更加戳到點子上。(最后這一句話仍值得斟酌、改進)

最后,我相信編寫軟件的本質是盡可能地應用 domain processes 來讓你的代碼更加易讀和更加可維護。

Resourceful 控制器在這兩個方面做得并不好。首先,它們不易讀,因為您傾向于根據數據來構建它們,而不是根據領域來構建它們。這樣的話,你就會丟失上下文對照。你表現了數據的處理方式,但卻沒有說明到底發生什么了,也沒有說明你使用哪個過程進行處理。

第二,你沒有針對可維護性進行優化。由于你是根據數據結構來構建的,因此你也會跟著耦合進去。實際上,您的領域模型在不斷發展,數據結構也在不斷發展。如果你的數據結構處理著多個過程或領域的多個部分,那你將很難進行調整。

laravel框架中文手冊?一個實際的例子

因為理論很無聊,上代碼更加容易解釋,所以我們來看一個實際的例子。

假設您正在構建一個應用,它允許用戶去組織事件。您想提供一種創建,更新和刪除這些事件的方法。這是一種非常典型的例子,你會用 CRUD 的方式來考慮實現它。那么,讓我們看看就這樣一個 resourceful 控制器是如何被轉換的。

首先我們來看看路由:

Route::get('events', [EventController::class, 'index']);
Route::get('events/create', [EventController::class, 'create']);
Route::post('events', [EventController::class, 'store']);
Route::get('event/{event}', [EventController::class, 'show']);
Route::get('events/{event}/edit', [EventController::class, 'edit']);
Route::put('events/{event}', [EventController::class, 'update']);
Route::destroy('events/{event}', [EventController::class, 'destroy']); 

現在對應的控制器:

<?php
namespace AppHttpControllers;
use AppModelsEvent;
final class EventController
{public function index(){// ...}public function create(){// ...}public function store(){// ...}public function show(Event $event){// ...}public function edit(Event $event){// ...}public function update(Event $event){// ...}public function destroy(Event $event){// ...}
}

laravel 定時任務,這個 EventController 處理所有的 CRUD 請求,展示事件列表,展示指定的事件,創建一個事件,更新一個現存的事件和刪除一個事件。

來看看 index 方法的細節:

public function index()
{$events = Event::paginate(10);return view('events.index', compact('events'));
}

在這個方法中,我們檢索出事件們,然后交給視圖讓它去展示到一個分頁列表中。 到目前為止都還好。但是你現在想實現一個方法,用不同的頁面去查看過去和即將來的事件。讓我們看看如何在 index 方法中實現它:

public function index(Request $request)
{if ($request->boolean('past')) {$events = Event::past()->paginate(10);} elseif ($request->boolean('upcoming')) {$events = Event::upcoming()->paginate(10);} else {$events = Event::paginate(10);}return view('events.index', compact('events'));
}

呃啊!看起來好亂啊。盡管我們已經用 Eloquent scopes 來隱藏查詢邏輯,但是還是有很丑的鏈式語句。我們來看看如何用單行為控制器來代替它。

每個單行為控制器只執行一件事情,僅僅一件事情。

laravel設計模式,首先,我們不使用查詢參數去獲得不同的事件列表,而是使用專用路由去實現它。

Route::get('events', ShowAllEventsController::class);
Route::get('events/past', ShowPastEventsController::class);
Route::get('events/upcoming', ShowUpcomingEventsController::class);

這個路由比之前的要長一些,但是這個比之前的要更有表達力。你可以一下子辨識出哪一個控制器處理哪一個特定的邏輯。如果你對比一下 URL,你會看到在可讀性上改進了一些:

# Before
/events
/events?past=true
/events?upcoming=true
# After
/events
/events/past
/events/upcoming

現在來看其中一個控制器。就看 ShowUpcomingEventsController 這個控制器:

<?php
namespace AppHttpControllers;
use AppModelsEvent;
final class ShowUpcomingEventsController
{public function __invoke(){$events = Event::upcoming()->paginate(10);return view('events.index', compact('events'));}
} 

丑陋的 if 語句沒了, and has made way for the same readable three liner we had from our first CRUD controller example. But instead of having all of the other CRUD operations we now have a dedicated controller for a dedicated action.

簡單,易讀,便于維護。

laravel框架關鍵技術解析。你可能會問自己,這樣做值么,畢竟之前的 if 語句也沒那么壞吧?但是我想向你展示的是你正在為未來的改進做優化,并改進維護性。下次你想要對這三個頁面做任何指定改變的時候,你會知道在哪里改,并且不需要艱難地更新一個 if 語句。

當然,上面的例子很簡單,我們來看一個更復雜一點的。我們試試重構 create 和 store 方法:

public function create()
{return view('events.create');
}
public function store(Request $request)
{$data = $request->validate(['name' => 'required','start' => 'required','end' => 'required|after:start',])$event = Event::create($data);return redirect()->route('event.show', $event);
}

我們要做的就是把這兩個方法移到專用的控制器,這樣更好地解釋了這些方法做了啥。這些方法更好地服務于你,比起把它們放在一個叫做 ScheduleNewEventController 的控制器中。我們接著更新這個控制器的路由:

Route::get('events/schedule', [ScheduleNewEventController::class, 'showForm']);
Route::post('events/schedule', [ScheduleNewEventController::class, 'schedule']);

我不會向你展示一個確切的控制器,因為它們有和上面的例子一樣,有兩個方法,只不過把 showForm 和 schedule 重新命名為更能表達它們干了啥的名字。即使這個不是單行為控制器,但是方法論是一樣的:把你應用中的專用行為(方法)和它對應的控制器拆分到一起。

好了,現在你已經看了單行為控制器的例子了。你可能會想,這會導致越來越多的文件。但事實上,這個根本就不是問題。文件多又沒啥。有更多、更小、更容易維護的文件比有更大、更難分析的要好。你可以打開一個單行為控制器的文件,然后快速掃描代碼,馬上就能知道這是干嘛的。

php定時器、我經常把他們分組到不同的目錄,這些目錄負責領域的各個部分。這讓你從文件結構的角度看控制器時,更加容易。

拆分控制器也讓你跟容易找到特定的一個控制器。想象一下,你要尋找那個可以安排事件的控制器時。現在你只需要按照文件名搜索編輯器,而不是一個通用的 EventController。

其他情況

我也被問到是否要對所有控制器執行此操作。不總是。在命名控制器時,我傾向于嚴謹且簡潔,但我也會像你一樣適應各種情況。

當然,有時候你還是想用 resourceful 控制器。比如在你構建 RESTful API 時。這樣做是很有意義,因為你經常直接與數據本身交互,而沒有經常與領域或任何進程進行交互。CMS(內容管理系統)或 Laravel Nova 等應用程序就是最好的例子。

laravel文檔,但是在需要的時候,您最好問問自己的方案是否更接近領域和處理過程。在需要根據領域執行操作的時候,比如 GraphQL 之類的或 API 之類的 RPC ,這樣做可能更適合。

結論

我希望這有一點見地,你現在能更理解我為什么如此喜歡單行為控制器了吧。我相信,結合小的 classes,再使用無處不在的語言、顯式地命名,會帶來更可維護的代碼,甚至是控制器,不僅僅是領域對象。但是正如我開頭所說,選擇能幫助你的部分,好好分辨哪些適用于你,哪些不行。

更多學習內容請訪問:

八重櫻:騰訊T3-T4標準精品PHP架構師教程目錄大全,只要你看完保證薪資上升一個臺階(持續更新)?zhuanlan.zhihu.com
42062154b2f2b1ec79cc7c76a12f65bc.png

以上內容希望幫助到大家,很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那里入手去提升,對此我整理了一些資料,包括但不限于:分布式架構、高可擴展、高性能、高并發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階干貨需要的可以免費分享給大家,需要的可以加入我的官方群點擊此處。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/110540.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息