練習時間30分鐘
今天想跟大家達成一個共識,之前在 小練習 – 共識 Controller 與 URL 這邊文章中,有提到 Controller 與 URL ,因此建議Controller 裡面的方法都要對應到一個網址以及HTTP動作,以下是基於 RESTful 設計模式的 API,AnimalController 為例。
方法名稱 | 定義 | 網址 (HTTP動詞 + 網址) |
index | 動物列表資料 | GET /v1/api/animals |
store | 建立動物資料 | POST /v1/api/animals |
show | 查看單一動物資料 | GET /v1/api/animals/{animal} |
update | 更新修改動物資料 | PATCH | PUT /v1/api/animals/{animal} |
destroy | 移除動物資料 | DELETE /v1/api/animals/{animal} |
若因為業務邏輯越來越複雜,導致方法越來越多,如果有物件導向的觀念,或許會設法把,functroller 做拆分,建議Controller 裡面,不要再有其他不會對應到 網址的方法,建議使用 Service 來輔助,因此非常建議,Controller 裡面就定義上面表格的方法就好。
要怎麼建立 Service 簡單來說他就是另外建立的一個 class 類別,如果你一開始就是接觸Laravel 可能不太懂物件導向,建議可以多了解一下物件導向,可以更深入 Laravel 到底層設計。
建議把 Service 建立在 Laravel 專案中的 app\Services 資料夾中,這個資料夾就要自己新建了,有了這個資料夾,定義他要來操作Animal 動物的資源的話,就在這個資料夾當中建立一個 AnimalService.php 的檔案,裡面建立一個 AnimalService 類別。
<?php
namespace App\Services;
class AnimalService
{
}
這時候你就可以將你的 Controller 拆分到這個 Service 當中,你可以依照不同的商業邏輯拆分不同的小方法 在《使用Laravel 8 PHP主流框架打造RESTful API(iT邦幫忙鐵人賽系列書)》 這本書中,整個重構的章節都在說明如何拆分,很重要的一點就是測試程式,在重構的時候,建議要有足夠的測試,不然很有可能因為你的修改而造成新的 bug。
不過這篇文章主要是說明,如何使用 Service 來輔助 Controller ,假設你的內容,你可以在 原本的 AnimalController 檔案中加入以下程式碼
<?php
namespace App\Http\Controllers\Api\V1\Animal;
use App\Models\Animal;
use App\Services\AnimalService;
use Illuminate\Http\Request;
class AnimalController extends Controller
{
private $service
public function __construct(AnimalService $animalService)
{
$this->service = $animalService;
}
public function index(){}
public function store(Request $request){}
public function show(Animal $animal){}
public function update(Request $request, Animal $animal){}
public function destroy(Animal $animal){}
}
將需要輔助的 Controller 加上以上粗體字,引用 AnimalService 類別,並寫在 AnimalController 類別中定義一個私有元素 $service (這邊我自己是習慣講相同資源名稱的省略),接著建立一個建構子方法 __construct (前方的底線是兩個 「 _ 」 喔!),並且設定變數傳入一個 AnimalService 類別的$animalService 變數,這裡 Laravel 會自動依賴注入這個參數,最後在建構子的方法中撰寫
$this->service = $animalService;
將 AnimalController 定義的私有變數 service 設定為依賴注入的 $animalService;
接著在 AnimalController 方法中就可以使用以下方式取的得 AnimalService 撰寫的方法,假設 AnimalService 裡面我有撰寫一個 doSomething
<?php
namespace App\Services;
class AnimalService
{
public function doSomething()
{
return '做一些事情';
}
}
這樣的話你可以在 剛剛修改好的 controller 使用以下方式呼叫 AnimalService 類別的 doSomething(),假設Service的方法是要在 AnimalController 的 index 方法使用
<?php
namespace App\Http\Controllers\Api\V1\Animal;
use App\Models\Animal;
use App\Services\AnimalService;
use Illuminate\Http\Request;
class AnimalController extends Controller
{
private $service
public function __construct(AnimalService $animalService)
{
$this->service = $animalService;
}
public function index()
{
return $this->service->doSomething();
}
}
這樣就可以輕易拿到 doSomething 方法回傳的字串喔!
以上是簡單的範例,但這邊複習一下,建立在我們達成的共識回答以下問題,歡迎留言給我!
- 如上範例 app\Http\Controllers\Api\V1\Animal\AnimalController.php 檔案中定義的 index 方法通常是在做什麼事情的? (參考:小練習 – 共識 Controller 與 URL、小練習 – 共識 Controller function)
- 請求什麼網址可以來到index ?(參考:小練習 – 共識 Controller 與 URL)
- 請問如上範例,他會回傳什麼資料顯示於畫面上?