iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Modern Web

後端菜雞仔想學 Laravel系列 第 17

Route Model Binding:Laravel 神奇的查詢利器

  • 分享至 

  • xImage
  •  

查詢單一產品的資料

[ GET ] api/products/{product} 對應到的是 ProductController 的 show 方法

查詢邏輯

有找到資料會回傳特定的產品資料。

ProductController.php


/**
* Display the specified resource.
* 查詢特定 ID 的產品資料
*/
public function show(Product $product)
{
    // 回傳特定產品資料
    return response(new ProductResource($product), Response::HTTP_OK);
        
}

使用 Postman 測試

https://ithelp.ithome.com.tw/upload/images/20241001/20169300kpGVg0zB4M.jpg

顯示 200 狀態碼及產品資料,所以測試成功!

聊聊這個 show 方法是怎麼運作的

這個方法主要是用來取得單一產品的詳細資料,這通常是在 API 裡 GET /products/{id} 這樣的路由使用,負責回傳單一產品的內容。

分配路由

在我的 Controller & Route:來指派店長跟分配店員吧! 文章裡有提到:
我要分配給一位自帶分身術的店員,承攬所有引導工作。
就是 Laravel 的內建方法:apiResource
可以把 URI 自動對應到 ProductController 內相對應的方法。

Route::apiResource('products', ProductController::class);

那如果不是使用 apiResource 自動對應,原本此路徑分配的路由應該是長這樣子:

Route::get('/products/{product}', [ProductController::class, 'show']);

參數 $product:

Laravel 提供了一個很方便的功能叫 Route Model Binding,意思就是它會自動根據 URL 上的 id 去資料庫抓出相對應的產品資料,然後傳進這個方法裡。

例如:
當你訪問 GET /products/1,它會自動幫你找到 id 是 1 的產品,然後這個產品資料就會被當成參數 $product。

new ProductResource($product):

將 $product 資料建立一個新的 ProductResource 物件。
而且這個資源物件會把我們的產品資料轉換成 JSON 格式。

簡單來說,ProductResource 就是負責把產品資料變成前端比較容易處理的格式,這樣 API 回傳的資料會更有一致性。

整個流程的運作

  1. 當使用者訪問 GET /products/1 時,Laravel 會幫你從資料庫自動找到 ID = 1 的產品,然後傳到 show 方法裡面。
  2. 然後 ProductResource 會把這個產品資料轉換成 JSON 格式。
  3. 接著建立 HTTP 回應,並將此 JSON 格式的資料回傳。

接著聊聊什麼是 Route Model Binding?

這是 Laravel 提供的一個非常方便的功能!
當你使用 Route Model Binding 時,Laravel 會根據 URL 上的 ID 或其他參數,從資料庫中找到對應的模型物件(例如一筆商品資料),然後自動把它傳遞到控制器的方法裡。

而 Route Model Binding 又分為:

  • 隱式(Implicit)Binding
  • 顯式(Explicit)Binding

隱式(Implicit)Binding

上述做的查詢單一產品資料範例就是使用 Implicit Binding。
菜雞仔如我,覺得 Implicit Binding 就是最方便的XDDD

隱式綁定的條件:

URL 參數名稱必須與控制器方法中的參數名稱相同,且該參數對應的模型名稱與 URL 中的參數名稱也要一致!
例如: {product} 對應 Product 模型。
Laravel 會根據模型的主鍵(預設為 id)自動查詢。

顯式(Explicit)Binding

有時候你可能希望用非主鍵來進行查詢,或是需要自定義查詢邏輯,這時就可以使用 Explicit Binding。

非主鍵查找

假設我們希望用商品的 slug 而不是 id 來查詢商品,那可以這樣設定:

Route::get('/products/{product:slug}', [ProductController::class, 'show']);

我們告訴 Laravel 請根據 slug 欄位來查詢對應的商品,而不是預設的 id。

自定義綁定邏輯

如果你需要完全自定義的查詢邏輯,可以在 RouteServiceProvider 中手動定義:

use App\Models\Product;

public function boot()
{
    parent::boot();

    // 自定義 Route Model Binding
    Route::bind('product', function ($value) {
        return Product::where('slug', $value)->firstOrFail();
    });
}

這樣,當路由中出現 {product} 時,Laravel 就會按照你自定義的查詢邏輯去查詢資料。


可以參考我厲害學姊的文章:Laravel routes
搭配參考官方文件:Laravel Route Model Binding


上一篇
查找問題的好方法:來 log log 吧!
下一篇
paginate:將很多細節做得好好的小助理
系列文
後端菜雞仔想學 Laravel30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言