> ## 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 10 升級到 11

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

## 前言

Laravel 11 於 2024 年 3 月發佈。本指南說明從 Laravel 10.x 升級到 11.x 的步驟。

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

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

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

***

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

### 影響程度：高

* 更新依賴套件
* 應用程式結構變更
* 浮點數型別變更
* 變更欄位時屬性的保留
* SQLite 最低版本
* Sanctum 更新

### 影響程度：中

* Carbon 3
* 密碼再雜湊
* 秒級速率限制
* Spatie Once 套件

### 影響程度：低

* 移除 Doctrine DBAL
* Eloquent 模型的 `casts` 方法
* 空間型別的變更
* `Enumerable` contract
* `UserProvider` contract
* `Authenticatable` contract

***

## 升級步驟

### 更新依賴套件

**影響程度:高**

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

```json theme={null}
{
  "require": {
    "laravel/framework": "^11.0",
    "nunomaduro/collision": "^8.1"
  }
}
```

若有使用其他套件也一併更新。

```json theme={null}
{
  "require": {
    "laravel/breeze": "^2.0",
    "laravel/cashier": "^15.0",
    "laravel/dusk": "^8.0",
    "laravel/jetstream": "^5.0",
    "laravel/octane": "^2.3",
    "laravel/passport": "^12.0",
    "laravel/sanctum": "^4.0",
    "laravel/scout": "^10.0",
    "laravel/spark-stripe": "^5.0",
    "laravel/telescope": "^5.0",
    "livewire/livewire": "^3.4",
    "inertiajs/inertia-laravel": "^1.0"
  }
}
```

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

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

若有使用 Cashier Stripe、Passport、Sanctum、Spark Stripe、Telescope，需要將 migration 發佈到應用程式中。

```shell theme={null}
php artisan vendor:publish --tag=cashier-migrations
php artisan vendor:publish --tag=passport-migrations
php artisan vendor:publish --tag=sanctum-migrations
php artisan vendor:publish --tag=spark-migrations
php artisan vendor:publish --tag=telescope-migrations
```

若有使用 Laravel installer 也請一併更新。

```shell theme={null}
composer global require laravel/installer:^5.6
```

若原本手動追加 `doctrine/dbal`，現在可以移除。Laravel 11 已經不再依賴此套件。

***

## PHP 版本需求

**影響程度:高**

Laravel 11 需要 **PHP 8.2.0 以上**。此外 Laravel 的 HTTP 客戶端需要 **curl 7.34.0 以上**。

***

## 應用程式結構變更

**影響程度:高**

Laravel 11 中預設的應用程式結構被簡化了。Service Provider、middleware、設定檔的數量大幅減少。

不過 **不建議** 將 Laravel 10 應用程式升級到 Laravel 11 時同時嘗試遷移應用程式結構。Laravel 11 設計為也支援 Laravel 10 的應用程式結構。

主要結構變更點：

* 在 `bootstrap/app.php` 直接設定 middleware、例外處理器、路由
* 廢止 `app/Http/Kernel.php`，整合到 `bootstrap/app.php`
* 減少預設的 Service Provider 數量，改由 `bootstrap/providers.php` 管理
* 減少 `config/` 目錄的檔案數量（需要時可用 `php artisan config:publish` 公開）

***

## 破壞性變更 (Breaking Changes)

### 認證

#### 密碼再雜湊

**影響程度:中**

Laravel 11 中，若認證時 hash 演算法的「work factor」有變更，會自動重新雜湊密碼。

若 `User` model 的密碼欄位名稱不是 `password`，請在 model 的 `authPasswordName` 屬性中指定。

```php theme={null}
class User extends Authenticatable
{
    protected $authPasswordName = 'custom_password_field';
}
```

要停用此功能請在 `config/hashing.php` 加入以下設定。

```php theme={null}
'rehash_on_login' => false,
```

#### `UserProvider` contract

**影響程度:低**

`Illuminate\Contracts\Auth\UserProvider` contract 新增了 `rehashPasswordIfRequired` 方法。若你有實作此介面的類別，請新增該方法。

```php theme={null}
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
```

#### `Authenticatable` contract

**影響程度:低**

`Illuminate\Contracts\Auth\Authenticatable` contract 新增了 `getAuthPasswordName` 方法。若你有實作此介面的類別，請新增該方法。

```php theme={null}
public function getAuthPasswordName()
{
    return 'password';
}
```

***

### 資料庫

#### SQLite 最低版本

**影響程度:高**

若使用 SQLite，需要 **SQLite 3.26.0 以上**。

另外，Laravel 11 新建專案的預設資料庫 driver 已改為 SQLite。

#### 變更欄位時的屬性保留

**影響程度:高**

變更欄位時，必須明確指定所有想在變更後保留的 modifier。未指定的屬性將被刪除。

```php theme={null}
// Laravel 10 會保留 unsigned、default、comment
Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')->nullable()->change();
});

// Laravel 11 需明確指定所有屬性
Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')
        ->unsigned()
        ->default(1)
        ->comment('The vote count')
        ->nullable()
        ->change();
});
```

若不想更新所有既有 migration，請將 migration 壓縮。

```shell theme={null}
php artisan schema:dump
```

#### 浮點數型別變更

**影響程度:高**

migration 的 `double` 與 `float` 欄位型別已在所有資料庫統一。

```php theme={null}
// double: 不再需要 total 與小數位數的引數
$table->double('amount');

// float: 只有指定精度的可選引數
$table->float('amount', precision: 53);
```

`unsignedDecimal`、`unsignedDouble`、`unsignedFloat` 方法已被移除。若仍要使用 `unsigned` 屬性請透過 method chain 指定。

```php theme={null}
$table->decimal('amount', total: 8, places: 2)->unsigned();
$table->double('amount')->unsigned();
$table->float('amount', precision: 53)->unsigned();
```

#### Eloquent 模型的 `casts` 方法

**影響程度:低**

Eloquent 基底模型類別新增了 `casts` 方法。若應用程式的 model 中定義了名為 `casts` 的 relation，因名稱衝突需要變更。

#### MariaDB 專用 driver

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

Laravel 11 新增了 MariaDB 專用的資料庫 driver。連線 MariaDB 時可以在設定中使用 `mariadb` driver。

```php theme={null}
'driver' => 'mariadb',
```

#### 空間型別的變更

**影響程度:低**

空間欄位型別已在所有資料庫統一。請改用 `geometry` 或 `geography`，而不是 `point`、`lineString`、`polygon` 等方法。

```php theme={null}
$table->geometry('shapes');
$table->geography('coordinates');
```

若要明確指定型別或空間參考系統，請傳入 `subtype` 與 `srid`。

```php theme={null}
$table->geometry('dimension', subtype: 'polygon', srid: 0);
$table->geography('latitude', subtype: 'point', srid: 4326);
```

#### 移除 Doctrine DBAL

**影響程度:低**

Laravel 已移除對 Doctrine DBAL 的依賴。以下類別與方法已被刪除。

* `Schema\Builder::useNativeSchemaOperationsIfPossible()`
* `Connection::getDoctrineConnection()`
* `Connection::getDoctrineSchemaManager()`
* `Connection::registerDoctrineType()`
* `DatabaseManager::registerDoctrineType()`
* `Schema\Grammars\ChangeColumn` 類別
* `Schema\Grammars\RenameColumn` 類別

資料庫檢查請改用 `Schema::getTables()`、`Schema::getColumns()`、`Schema::getIndexes()`、`Schema::getForeignKeys()` 等新的原生方法。

***

### 日期

#### Carbon 3

**影響程度:中**

Laravel 11 同時支援 Carbon 2 與 Carbon 3。若升級到 Carbon 3，請注意 `diffIn*` 方法會回傳浮點數，並以負值表示時間方向。

***

### 速率限制

#### 秒級速率限制

**影響程度:中**

Laravel 11 支援秒級（而非分級）的速率限制。`GlobalLimit`、`Limit` 類別的 constructor 開始接收秒為單位的值。

```php theme={null}
// 變更前（分為單位）
new GlobalLimit($attempts, 2); // 2 分鐘

// 變更後（秒為單位）
new GlobalLimit($attempts, 2 * 60); // 120 秒
```

`Limit` 類別的 `decayMinutes` 屬性已重新命名為 `decaySeconds`，並改為秒為單位。

`ThrottlesExceptions` 與 `ThrottlesExceptionsWithRedis` 的 constructor 也開始以秒為單位接收。

```php theme={null}
new ThrottlesExceptions($attempts, 2 * 60);
new ThrottlesExceptionsWithRedis($attempts, 2 * 60);
```

***

### 套件

#### 發佈 Service Provider

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

Laravel 11 的新建應用程式已不再有 `config/app.php` 的 `providers` 陣列。若在套件中發佈 Service Provider，請使用 `ServiceProvider::addProviderToBootstrapFile` 方法。

```php theme={null}
use Illuminate\Support\ServiceProvider;

ServiceProvider::addProviderToBootstrapFile(Provider::class);
```

***

### Sanctum

#### Sanctum 更新

**影響程度:高**

Laravel 11 不支援 Sanctum 3.x。請將 `composer.json` 中的 Sanctum 依賴更新為 `^4.0`。

Sanctum 4.0 不再自動載入 migration。請以下列指令發佈。

```shell theme={null}
php artisan vendor:publish --tag=sanctum-migrations
```

另外，請更新 `config/sanctum.php` 的 middleware 設定。

```php theme={null}
'middleware' => [
    'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
    'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
    'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
],
```

***

### Spatie Once 套件

**影響程度:中**

Laravel 11 現在提供自有的 [`once` 函式](https://laravel.com/docs/11.x/helpers#method-once)。若有使用 `spatie/once` 套件，請從 `composer.json` 中移除以避免衝突。

***

## 總結

Laravel 11 是包含大規模結構變更的版本，但 Laravel 10 的應用程式結構仍可正常運作，可以逐步遷移。

| 變更點                   | 影響程度 | 對應                                 |
| --------------------- | ---- | ---------------------------------- |
| 更新 `composer.json` 依賴 | 高    | 改為 `laravel/framework ^11.0`       |
| 必需 PHP 8.2            | 高    | 確認 PHP 版本                          |
| 變更欄位時的屬性保留            | 高    | 確認 `change()` 使用位置                 |
| 浮點數型別變更               | 高    | 確認 `double`/`float` 欄位定義           |
| 必需 SQLite 3.26.0+     | 高    | 確認 SQLite 版本                       |
| Sanctum `^4.0`        | 高    | 發佈 migration                       |
| Carbon 3              | 中    | 確認 `diffIn*` 方法的回傳值                |
| 秒級速率限制                | 中    | 將 `decayMinutes` 改為 `decaySeconds` |
| 移除 Doctrine DBAL      | 低    | 移轉到原生 schema 方法                    |

***

## 參考資料

* [官方升級指南（英文）](https://laravel.com/docs/11.x/upgrade)
* [laravel/laravel repository 差異（10.x → 11.x）](https://github.com/laravel/laravel/compare/10.x...11.x)
* [Laravel Shift](https://laravelshift.com) — 自動化升級的社群服務
* [Carbon 3 變更紀錄](https://github.com/briannesbitt/Carbon/releases/tag/3.0.0)


## Related topics

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