iT邦幫忙

2021 iThome 鐵人賽

DAY 5
0

路由架構

Breeze 已經架構好利用 inertia.js 取得 Login 等畫面的路由,不過為了解路由的運作,先用基礎的路由做說明。

專案已經預設好用於定義路由的檔案,分別是

routes/web.php
routes/api.php

web.php 目標用於網頁的請求處理,框架預先幫這裡的路由加上許多中介層(Middleware)幫助處理請求,像是處理 cookie 或是防止 CSRF。

對於 web 的 Middleware 設定位於

app\Http\Kernel.php

當中的 $middlewareGroups 參數。

開啟 web.php 我們可以看到已經有一組預設的路由

Route::get('/', function () {
    return view('welcome');
});

這就是前面我們執行 php artisan serve 之後讓我們可以在瀏覽器上看到預設畫面的路由。

在底下我們可以加上

Route::get('/greeting', function () {
    return 'Hello World';
});

然後存檔,再到瀏覽器輸入網址 http://127.0.0.1:8000/greeting
就可以看到老朋友 Hello World 的字樣了。

api.php

至於 api.php 顧名思義就是用來定義 api 路由的,打開可以看到這邊也有預設的路由

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

我們可以試著用瀏覽器請求這個路由,網址輸入

http://127.0.0.1:8000/api/user

應該會看到這個畫面

首先可以注意的是路由明明只寫了 /user, 為什麼會需要帶上 /api 的路由呢?

這是因為預設在 app\Providers\RouteServiceProvider.php 檔案中,已經設定好前綴了。

<!-- app\Providers\RouteServiceProvider.php -->
//...

/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    $this->configureRateLimiting();

    $this->routes(function () {
        Route::prefix('api') //這裡定義了前綴
            ->middleware('api')   
            ->namespace($this->namespace)
            ->group(base_path('routes/api.php'));

        Route::middleware('web')
            ->namespace($this->namespace)
            ->group(base_path('routes/web.php'));
    });
}

所以 api.php 當中的所有路由記得都要戴上 /api 在前面,才能正確地請求。

請求方法

對應不同的 HTTP 請求方法的路由:

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback); 

如果路由需要對應複數種類的請求:

Route::match(['get', 'post'], '/', $callback);

如果路由要對應所有種類的請求:

Route::any('/', $callback);

依賴注入請求實例

利用 Laravel 的服務容器(Service Container)功能,用 型別提示(Type hinting)可以直接將 Http 請求的實例注入到路由的函式中

use Illuminate\Http\Request;

Route::get('/ip', function (Request $request) {
    return $request->ip();
});

瀏覽器輸入 http://127.0.0.1:8000/api/ip 會出現 127.0.0.1

Request 物件是在請求週期最一開始的時候就將請求解析分裝好的產物,具體來說發生在 index.php 第52行的位置

// public/index.php 
$response = tap($kernel->handle(
    $request = Request::capture()
))->send();

可以從 Request 物件中很方便地取出請求的資訊,像是 Header ,Body 等,如果有建立好 Laravel 的用戶認證機制的話也可以直接取得登入使用者的資訊。

路由參數

實作上常常會在路由帶上資料庫的 id 參數,像這樣

Route::get('/user/{id}', function ($id) {
    return 'User '.$id;
});

可以同時使用多個參數,會依照順序對應到函式的參數上。
參數的字串要用字母,除此之外底線也是可以的。

Route::get('/posts/{post}/comments/{_comment}', function ($postId, $commentId) {
    return "post = $postId , _comment = $commentId";
});

用上述的路由然後在瀏覽器輸入網址 http://127.0.0.1:8000/api/posts/1/comments/2
就會出現

post = 1 , _comment = 2

如果跟依賴注入一起用的話,函式參數要先用注入實例,後面再依序排入參數

use Illuminate\Http\Request;
 
Route::get('/posts/{post}/comments/{_comment}',
    function (Request $request, $postId, $commentId) {
        $ip = $request->ip();
        return "From ip: $ip ,post = $postId , _comment = $commentId";
    }
);

可以設定路由參數為非必要,當參數是非必要的時候要注意設定預設值

Route::get('/user/{name?}', function ($name = 'John') {
    return $name;
});

綁定 Model

在路由中帶入參數通常是為了根據參數搜尋出單筆數據進行處理,如果該參數是資料主鍵的話,Laravel 提供了捷徑直接搜尋出該筆資料以供處理

use App\Models\User;

Route::get('/users/{user}', function (User $user) {
    return $user->email;
});

這邊宣告了路由函式的參數型別是 User Model,而在路徑中有著名為 user 的參數,這種情況下 Laravel 會自動將 user 參數當作 User 主鍵值進行查詢,查詢成功就可以從 $user 取得該筆資料,查詢失敗則直接回傳 404 查詢失敗回應。

命名路由

可以給路由加上名稱標籤

Route::get('/user/{id}/profile', function ($id) {
    //
})->name('profile');

這樣當要重新導向的時候可以很方便的參照,也可以帶參數

return redirect()->route('profile', ['id' => 1]); 

路由分組

當有數個路由需要用到相同的 Middleware 進行處裡的時候,就會建立分組

Route::middleware(['auth:api', 'cache.headers'])->group(function () {
    Route::get('/user', function () {
        // handle function
    });

    Route::get('/user/profile', function () {
        // handle function
    });
});

像這樣 '/user' 跟 '/user/profile' 兩個路由收到請求時,都會先經由 'auth:api', 'cache.headers' 對請求進行處理。

對於分組也可以定義共通的路由前綴,像是把上面的 user 提取出來變成前綴

Route::group(
    [
        'prefix' => 'user',
        'middleware' => ['auth:api', 'cache.headers'],
    ], function () {
        Route::get('/', function () {
            // handle function
        });

        Route::get('/profile', function () {
            // handle function
        });
    }
);

查看路由清單

可以用指令查看目前定義的路由們,會包含各路由應用的 middleware 列表

 sail artisan route:list

References

Laravel Routing
https://stackoverflow.com/questions/54486616/how-passing-request-instance-in-methods-work-in-laravel

上一篇
使用 Breeze 建立基礎專案框架
下一篇
Controller
系列文
Laravel 實務筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言