Laravel Controller中的callAction
前言:
我們都知道在Laravel的router中定義好路徑,並且指定到要執行的controller method中,連到該路徑就會進入指定的method中執行,
但是在這之前Laravel做了多少事情才讓資料流進入到到controller method中呢?今天我們來往前走一步,那就是controller中的callAction method
參考資料
callAction做了什麼
在我們自己定義的Controller中,都會去繼承Laravel framework中的BaseController,裡面就有個method大致上如下
1 2 3 4 5 |
public function callAction($method, $parameters) { // ... 你的邏輯 return $this->{$method}(...array_values($parameters)); } |
大致上就是用動態呼叫的方式把call你在router中定義的method name,以及將參數送過去
簡單來說,callAction會是你定義的controller method的進入點以及離開點,所以我們可以複寫controller中的callAction method來達到進入controller處理邏輯前做一些,以及邏輯處理完return資料前再做一些事情
我們改了什麼
我們先覆寫controller中的callAction method
1 2 3 4 5 6 7 |
public function callAction($method, $parameters): array|ServerResponse { $ctx = new RequestCtx(method: $method, parameters: $parameters); $this->_pre_call($ctx); $this->_call($ctx); return $this->_post_call($ctx); } |
其中,我們自行定義一個RequestCtx Class,目的在於存下原本controller的傳入值以及預計要return的回傳值,方便處理
我們分成三個動作,_pre_call, _call, 以及_post_call 三個動作,分別是預先處理資料、真正呼叫controller method 做事情,最後處理retrun 值
1 2 3 4 5 |
protected function _pre_call(RequestCtx $ctx): RequestCtx { ... return $ctx; } |
_pre_call比較不重要,這邊就先不描述,主要就是針對傳入值做一些進入controller前需要的init或是validate
1 2 3 4 5 6 |
protected function _call(RequestCtx $ctx): RequestCtx { $result = parent::callAction($ctx->get_method(), $ctx->get_parameters()); $ctx->set_result($result); return $ctx; } |
_call,就是實際上去呼叫parent::callAction,將原本該有的method name以及parameter傳入後儲存結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
protected function _post_call(RequestCtx $ctx): ServerResponse|array { $result = $ctx->get_result(); if ($result instanceof ServerResponse) { return $result; } $content = $this->_serialize_content( result: $result, parsers: $this->_get_serializers() ); return ['data' => $content]; } |
_post_call會處理在return前的狀況,這邊處理的內容是,如果controller處理完已經是一個ServerResponse那麼就直接return
如果不是,我們另外將資料序列化做好,放入data中再回傳,確保未來回傳的資料每個method都相同