> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 回應（Response）

> 說明 Laravel 的回應種類，以及如何從控制器回傳合適的回應。

## 什麼是回應

控制器或路由必須向使用者的瀏覽器回傳某種**回應**。
Laravel 提供簡潔的機制，讓字串、陣列、view、redirect、JSON 等各種形式的回應都能輕鬆傳回。

## 基本回應

### 回傳字串

最簡單的回應是回傳字串。
Laravel 會自動轉為合適的 HTTP 回應。

```php theme={null}
Route::get('/', function () {
    return 'Hello World';
});
```

### 回傳陣列

回傳陣列時，Laravel 會自動轉為 JSON 形式回應。

```php theme={null}
Route::get('/users', function () {
    return [
        ['id' => 1, 'name' => '田中'],
        ['id' => 2, 'name' => '鈴木'],
    ];
});
```

<Info>
  將 Eloquent model 或 collection 直接 return 時也會自動轉為 JSON。因此常被用來輕鬆製作 API。
</Info>

### 回傳 Eloquent model

```php theme={null}
use App\Models\User;

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

## Response 物件

使用 `response()` helper，可回傳指定 HTTP 狀態碼與 header 的詳細回應。

```php theme={null}
Route::get('/home', function () {
    return response('Hello World', 200)
        ->header('Content-Type', 'text/plain');
});
```

`response()` 第 1 個引數是回應 body，第 2 個引數是 HTTP 狀態碼。

### 常用 HTTP 狀態碼

| 狀態碼   | 意義                           |
| ----- | ---------------------------- |
| `200` | OK（成功）                       |
| `201` | Created（資源建立成功）              |
| `204` | No Content（無內容）              |
| `301` | Moved Permanently（永久重新導向）    |
| `302` | Found（暫時重新導向）                |
| `404` | Not Found（找不到）               |
| `422` | Unprocessable Entity（驗證錯誤）   |
| `500` | Internal Server Error（伺服器錯誤） |

## View 回應

要從控制器顯示 Blade 樣板，使用 `view()`。
這是 Web 應用中最常見的回應。

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\View\View;

class HomeController extends Controller
{
    public function index(): View
    {
        $users = [
            ['name' => '田中', 'email' => 'tanaka@example.com'],
            ['name' => '鈴木', 'email' => 'suzuki@example.com'],
        ];

        return view('users.index', ['users' => $users]);
    }
}
```

`view()` 第 1 個引數是 view 名稱，第 2 個引數是要傳給 view 的資料陣列。

<Tip>
  在回傳型別上明確標示 `Illuminate\View\View`，可讓程式碼意圖更清楚。
</Tip>

### 以 `response()->view()` 精細控制

若要同時指定狀態碼或 header，可使用 `response()->view()`。

```php theme={null}
return response()
    ->view('errors.404', ['message' => '找不到頁面'], 404);
```

## Redirect

### 基本 redirect

`redirect()` helper 會回傳 redirect 回應。
常用於表單送出後導向另一頁面。

```php theme={null}
use Illuminate\Http\RedirectResponse;

Route::get('/old-page', function (): RedirectResponse {
    return redirect('/new-page');
});
```

在控制器中的範例：

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function store(Request $request): RedirectResponse
    {
        // 儲存文章的處理...

        return redirect('/posts');
    }
}
```

### 導向具名路由

使用 `route()` 函式，可不必寫 URL，改以路由名稱指定 redirect 目標。
URL 變更也不需修改，因此善用具名路由是最佳實務。

```php theme={null}
// 為路由命名
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
Route::get('/posts/{post}', [PostController::class, 'show'])->name('posts.show');
```

```php theme={null}
// 導向具名路由
return redirect()->route('posts.index');

// 傳入路由參數
return redirect()->route('posts.show', ['post' => $post->id]);
```

### 回到前一頁

用 `back()` 可回到使用者剛才所在的頁面。
常用於驗證失敗時的 redirect。

```php theme={null}
return back();

// 保留輸入資料回上一頁
return back()->withInput();
```

### 附帶 flash 訊息的 redirect

使用 `with()` 可在 redirect 時附帶 session 訊息。
方便在表單送出成功後顯示訊息。

```php theme={null}
return redirect('/posts')->with('success', '已建立文章。');
```

在 Blade 樣板中顯示訊息：

```blade theme={null}
@if (session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif
```

## JSON 回應

製作 API 時，用 `response()->json()` 回傳 JSON 回應。
會自動設定 `Content-Type: application/json` header。

```php theme={null}
use Illuminate\Http\JsonResponse;

Route::get('/api/users', function (): JsonResponse {
    $users = [
        ['id' => 1, 'name' => '田中'],
        ['id' => 2, 'name' => '鈴木'],
    ];

    return response()->json($users);
});
```

亦可指定狀態碼。

```php theme={null}
return response()->json(['message' => '已建立'], 201);
```

在控制器中的範例：

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(): JsonResponse
    {
        $users = User::all();

        return response()->json($users);
    }

    public function store(Request $request): JsonResponse
    {
        // 以驗證通過的資料建立（在 form request 或 $request->validate() 之後）
        $user = User::create($request->validated());

        return response()->json($user, 201);
    }
}
```

<Info>
  單純 return 陣列或 Eloquent model 也會變成 JSON 回應，但使用 `response()->json()` 可以更細緻地控制狀態碼與 header。
</Info>

## 回應 Header

以 `header()` 方法可為回應加上 HTTP header。

```php theme={null}
return response('Hello World')
    ->header('Content-Type', 'text/plain')
    ->header('X-Custom-Header', 'MyValue');
```

要一次設定多個 header 可使用 `withHeaders()`。

```php theme={null}
return response('Hello World')
    ->withHeaders([
        'Content-Type' => 'text/plain',
        'X-Custom-Header' => 'MyValue',
        'Cache-Control' => 'no-cache',
    ]);
```

## 實務範例：在控制器中的分工

以下整理依用途分工使用回應的範例。

<Steps>
  <Step title="定義路由">
    ```php theme={null}
    use App\Http\Controllers\PostController;

    Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
    Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create');
    Route::post('/posts', [PostController::class, 'store'])->name('posts.store');
    Route::get('/posts/{post}', [PostController::class, 'show'])->name('posts.show');
    Route::delete('/posts/{post}', [PostController::class, 'destroy'])->name('posts.destroy');
    ```
  </Step>

  <Step title="控制器的實作">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Models\Post;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\View\View;

    class PostController extends Controller
    {
        // 一覽顯示：回傳 view
        public function index(): View
        {
            $posts = Post::latest()->get();

            return view('posts.index', ['posts' => $posts]);
        }

        // 建立表單：回傳 view
        public function create(): View
        {
            return view('posts.create');
        }

        // 儲存：回傳 redirect
        public function store(Request $request): RedirectResponse
        {
            // 以驗證通過的資料建立（使用 form request 時）
            $post = Post::create($request->validated());

            return redirect()
                ->route('posts.show', ['post' => $post->id])
                ->with('success', '已建立文章。');
        }

        // 詳細顯示：回傳 view
        public function show(Post $post): View
        {
            return view('posts.show', ['post' => $post]);
        }

        // 刪除：回傳 redirect
        public function destroy(Post $post): RedirectResponse
        {
            $post->delete();

            return redirect()
                ->route('posts.index')
                ->with('success', '已刪除文章。');
        }
    }
    ```
  </Step>
</Steps>

<Tip>
  Web 應用中，`View` 與 `RedirectResponse` 的分工是基本。顯示型 action 用 `View`，變更型（建立、更新、刪除）action 在處理後回傳 `RedirectResponse` 是常見模式。
</Tip>

## 後續步驟

<Card title="Validation" icon="check-circle" href="/zh-TW/validation">
  在回傳回應前，確認以驗證檢查輸入資料的方式。
</Card>


## Related topics

- [Laravel Passkeys 初步調查（passkeys-server + @laravel/passkeys）](/zh-TW/blog/passkeys-introduction.md)
- [HTTP 用戶端](/zh-TW/http-client.md)
- [VoicevoxResponse - VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/response.md)
- [Laravel MCP](/zh-TW/mcp.md)
- [Laravel Telescope 實戰技巧](/zh-TW/blog/telescope-introduction.md)
