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

# 從 Laravel 11 升級到 12 指南

> 說明從 Laravel 11 升級至 12 的步驟與主要變更點

## 前言

Laravel 12 於 2025 年 2 月發佈。本指南說明從 Laravel 11.x 升級到 12.x 的步驟。

<Info>
  升級預估所需時間約為 **5 分鐘**。不過破壞性變更對應用程式的影響會因規模與使用的功能而異。
</Info>

### 使用 Laravel Shift 自動化升級

也可以使用 [Laravel Shift](https://laravelshift.com/) 自動化升級作業。Shift 會自動更新應用程式的相依套件與設定檔。

***

## 依影響程度分類的變更

### 影響程度：高

* 更新依賴套件
* 更新 Laravel installer

### 影響程度：中

* Eloquent `HasUuids` trait 與 UUIDv7

### 影響程度：低

* Carbon 3
* Concurrency 的結果 index 映射
* Container 的類別依賴解析
* image validation 排除 SVG
* 本機檔案系統磁碟的預設 root 路徑
* multi-schema 的資料庫檢查
* nested array request 的合併

***

## 升級步驟

### 更新依賴套件

**影響程度:高**

請更新 `composer.json` 中以下依賴。

```json theme={null}
{
  "require": {
    "laravel/framework": "^12.0"
  },
  "require-dev": {
    "phpunit/phpunit": "^11.0",
    "pestphp/pest": "^3.0"
  }
}
```

更新後執行以下指令安裝依賴。

```shell theme={null}
composer update
```

***

### 更新 Laravel installer

**影響程度:高**

若使用 Laravel installer CLI 建立新的 Laravel 應用程式，請更新為支援 Laravel 12.x 與[新的 starter kit](https://laravel.com/starter-kits) 的版本。

若以 `composer global require` 安裝時:

```shell theme={null}
composer global update laravel/installer
```

若是以 `php.new` 安裝，請依作業系統執行重新安裝的指令。

<Tabs>
  <Tab title="macOS">
    ```shell theme={null}
    /bin/bash -c "$(curl -fsSL https://php.new/install/mac/8.4)"
    ```
  </Tab>

  <Tab title="Windows PowerShell">
    ```shell theme={null}
    # 以系統管理員身份執行
    Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://php.new/install/windows/8.4'))
    ```
  </Tab>

  <Tab title="Linux">
    ```shell theme={null}
    /bin/bash -c "$(curl -fsSL https://php.new/install/linux/8.4)"
    ```
  </Tab>
</Tabs>

若使用 [Laravel Herd](https://herd.laravel.com) 的 bundle 版，請更新 Herd 自身至最新版本。

***

## 新 starter kit

Laravel 12 引入了取代原本 Breeze 或 Jetstream 的新 starter kit。執行 `laravel new` 時可用互動方式選擇前端 stack。

可用的 starter kit：

* **React** — Inertia 2、React 19、TypeScript、Tailwind 4、shadcn/ui
* **Vue** — Inertia 2、Vue Composition API、TypeScript、Tailwind 4、shadcn-vue
* **Svelte** — Inertia 2、Svelte 5、TypeScript、Tailwind 4、shadcn-svelte
* **Livewire** — Livewire、Tailwind 4、Flux UI

```shell theme={null}
laravel new my-app
```

執行指令會被提示選擇 starter kit。選好後只要安裝依賴並啟動開發伺服器即可。

```shell theme={null}
cd my-app
npm install && npm run build
composer run dev
```

<Info>
  升級既有的應用程式並不需要重新導入 starter kit。這是針對新專案的變更。
</Info>

***

## 破壞性變更 (Breaking Changes)

### Eloquent

#### `HasUuids` trait 與 UUIDv7

**影響程度:中**

`HasUuids` trait 已改為回傳 UUID v7（有序 UUID）。若想保留之前有序 UUID v4 的行為，請切換到 `HasVersion4Uuids` trait。

```php theme={null}
use Illuminate\Database\Eloquent\Concerns\HasUuids; // [tl! remove]
use Illuminate\Database\Eloquent\Concerns\HasVersion4Uuids as HasUuids; // [tl! add]
```

若原本使用 `HasVersion7Uuids` trait，請改為 `HasUuids` trait（行為相同）。

***

### 驗證

#### image validation 排除 SVG

**影響程度:低**

`image` validation rule 預設不再允許 SVG。若要允許 SVG，請明確指定。

```php theme={null}
use Illuminate\Validation\Rules\File;

'photo' => 'required|image:allow_svg'

// 或
'photo' => ['required', File::image(allowSvg: true)],
```

***

### 儲存

#### 本機檔案系統磁碟的預設 root 路徑

**影響程度:低**

若沒有在 `filesystems` 設定中明確定義 `local` disk，預設的 root 路徑已從 `storage/app` 改為 `storage/app/private`。

若要維持之前的行為，請在設定檔明確定義 `local` disk。

```php theme={null}
// config/filesystems.php
'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
],
```

***

### 資料庫

#### multi-schema 的資料庫檢查

**影響程度:低**

`Schema::getTables()`、`Schema::getViews()`、`Schema::getTypes()` 預設會回傳所有 schema 的結果。若要指定特定 schema，請傳入 `schema` 引數。

```php theme={null}
// 所有 schema 的資料表
$tables = Schema::getTables();

// 僅 'main' schema 的資料表
$tables = Schema::getTables(schema: 'main');
```

`Schema::getTableListing()` 預設會回傳附 schema 前綴的資料表名稱。

```php theme={null}
$tables = Schema::getTableListing();
// ['main.migrations', 'main.users', 'blog.posts']

$tables = Schema::getTableListing(schema: 'main', schemaQualified: false);
// ['migrations', 'users']
```

#### 資料庫 constructor 簽章變更

**影響程度:非常低**

`Illuminate\Database\Schema\Blueprint` 與 `Illuminate\Database\Grammar` 的 constructor 已改為要求以 `Connection` instance 作為第一個引數。

```php theme={null}
// Laravel <= 11.x
$grammar = new MySqlGrammar;
$grammar->setConnection($connection);

// Laravel >= 12.x
$grammar = new MySqlGrammar($connection);
```

另外，以下 API 已被刪除或標為棄用。

| API                                              | 狀態 |
| ------------------------------------------------ | -- |
| `Blueprint::getPrefix()`                         | 棄用 |
| `Connection::withTablePrefix()`                  | 刪除 |
| `Grammar::getTablePrefix()` / `setTablePrefix()` | 棄用 |
| `Grammar::setConnection()`                       | 刪除 |

資料表前綴請直接從 connection 取得。

```php theme={null}
$prefix = $connection->getTablePrefix();
```

***

### Concurrency

#### 結果 index 映射

**影響程度:低**

傳給 `Concurrency::run()` 的關聯陣列，結果會依對應的 key 回傳。

```php theme={null}
$result = Concurrency::run([
    'task-1' => fn () => 1 + 1,
    'task-2' => fn () => 2 + 2,
]);

// ['task-1' => 2, 'task-2' => 4]
```

***

### Container

#### 類別依賴解析的預設值

**影響程度:低**

DI Container 在解析類別 instance 時，會尊重類別屬性的預設值。

```php theme={null}
class Example
{
    public function __construct(public ?Carbon $date = null) {}
}

$example = resolve(Example::class);

// Laravel <= 11.x: 回傳 Carbon instance
// Laravel >= 12.x: 回傳 null
```

***

### Request

#### 巢狀陣列 request 的合併

**影響程度:低**

`$request->mergeIfMissing()` 現在可用點記號合併巢狀陣列資料。之前點記號的 key 會被直接建立為最上層 key。

```php theme={null}
$request->mergeIfMissing([
    'user.last_name' => 'Otwell',
]);
```

***

### 路由

#### 路由的優先順序

**影響程度:低**

有多個同名路由時的行為，在快取有與無下都已統一。無快取的路由中，最先註冊（而非最後）的路由會優先。

***

### 認證

#### `DatabaseTokenRepository` constructor 的變更

**影響程度:非常低**

`Illuminate\Auth\Passwords\DatabaseTokenRepository` 的 constructor 中 `$expires` 參數已從以分為單位改為以秒為單位。

***

### Carbon 3

**影響程度:低**

已移除對 Carbon 2.x 的支援。Laravel 12 應用程式必須使用 [Carbon 3.x](https://carbon.nesbot.com/guide/getting-started/migration.html)。

***

## 總結

Laravel 12 是相對容易升級的版本。以下整理主要注意事項。

| 變更點                       | 影響程度 | 對應                           |
| ------------------------- | ---- | ---------------------------- |
| 更新 `composer.json` 依賴     | 高    | 改為 `laravel/framework ^12.0` |
| 更新 Laravel installer      | 高    | `composer global update`     |
| `HasUuids` → UUIDv7       | 中    | 需要時切換到 `HasVersion4Uuids`    |
| `image` validation 排除 SVG | 低    | 要允許 SVG 時加上 `allow_svg`      |
| 本機 disk 預設 root 變更        | 低    | 於設定檔明確指定                     |
| 必需 Carbon 3               | 低    | 確認 API 相容性                   |

***

## 參考資料

* [官方升級指南（英文）](https://laravel.com/docs/12.x/upgrade)
* [laravel/laravel repository 差異（11.x → 12.x）](https://github.com/laravel/laravel/compare/11.x...12.x)
* [新的 starter kit](https://laravel.com/starter-kits)
* [Laravel Shift](https://laravelshift.com) — 自動化升級的社群服務
* [Carbon 3 遷移指南](https://carbon.nesbot.com/guide/getting-started/migration.html)


## Related topics

- [從 Laravel 12 升級到 13 指南](/zh-TW/blog/upgrade-12-to-13.md)
- [從 Laravel 10 升級到 11](/zh-TW/blog/upgrade-10-to-11.md)
- [從 Laravel 8 升級到 9](/zh-TW/blog/upgrade-8-to-9.md)
- [從 Laravel 9 升級到 10](/zh-TW/blog/upgrade-9-to-10.md)
