> ## 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` 契约
* `UserProvider` 契约
* `Authenticatable` 契约

***

## 升级步骤

### 更新依赖

**影响度:高**

请更新 `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,需要发布对应的迁移。

```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 Client 需要 **curl 7.34.0 或以上**。

***

## 应用目录结构变更

**影响度:高**

Laravel 11 简化了默认的应用目录结构。服务提供者、中间件、配置文件的数量都大幅减少。

不过,把 Laravel 10 的应用升级到 Laravel 11 时,**不建议**同时迁移目录结构。Laravel 11 从设计上就支持沿用 Laravel 10 的目录结构。

主要结构变化:

* 在 `bootstrap/app.php` 中直接配置中间件、异常处理、路由
* 废弃 `app/Http/Kernel.php`,合并进 `bootstrap/app.php`
* 减少默认服务提供者数量,并改由 `bootstrap/providers.php` 管理
* 减少 `config/` 目录里的文件数量(需要时可用 `php artisan config:publish` 发布)

***

## 破坏性变更(Breaking Changes)

### 认证

#### 密码的重新哈希

**影响度:中**

Laravel 11 会在认证时检测哈希算法的“work factor”是否变化,自动重新哈希密码。

如果 `User` 模型的密码字段名不是 `password`,请通过模型的 `authPasswordName` 属性指明。

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

要关闭这一功能,在 `config/hashing.php` 中加上:

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

#### `UserProvider` 契约

**影响度:低**

`Illuminate\Contracts\Auth\UserProvider` 契约新增了 `rehashPasswordIfRequired` 方法。如果你有实现该接口的类,请补上这个方法。

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

#### `Authenticatable` 契约

**影响度:低**

`Illuminate\Contracts\Auth\Authenticatable` 契约新增了 `getAuthPasswordName` 方法。如果你有实现该接口的类,请补上。

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

***

### 数据库

#### SQLite 最低版本

**影响度:高**

使用 SQLite 时需要 **SQLite 3.26.0 或以上**。

顺带一提,Laravel 11 新项目的默认数据库驱动改成了 SQLite。

#### 列变更时保留属性

**影响度:高**

修改列时,你必须显式指定所有想保留的修饰符。没有指明的属性会被删掉。

```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();
});
```

如果你不想改所有历史迁移,可以选择把迁移打包压平。

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

#### 浮点类型变更

**影响度:高**

`double` 和 `float` 迁移列类型在各数据库间被统一了。

```php theme={null}
// double:不再需要总位数和小数位数的参数
$table->double('amount');

// float:只用一个可选的精度参数
$table->float('amount', precision: 53);
```

`unsignedDecimal`、`unsignedDouble`、`unsignedFloat` 方法被移除。要继续使用 `unsigned` 属性,请以方法链的方式加。

```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` 方法。如果你在应用的模型中定义了名为 `casts` 的关联,会出现命名冲突,需要重命名。

#### MariaDB 专用驱动

**影响度:非常低**

Laravel 11 加入了针对 MariaDB 的专用数据库驱动。连接 MariaDB 时可以在配置中使用 `mariadb` 驱动。

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

#### 空间类型变更

**影响度:低**

空间列类型在各数据库间被统一了。不再使用 `point`、`lineString`、`polygon` 等方法,请改用 `geometry` 或 `geography`。

```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` 类的构造函数现在接受秒数。

```php theme={null}
// 变更前(分钟)
new GlobalLimit($attempts, 2); // 2 分钟

// 变更后(秒)
new GlobalLimit($attempts, 2 * 60); // 120 秒
```

`Limit` 类的 `decayMinutes` 属性重命名为 `decaySeconds`,单位变为秒。

`ThrottlesExceptions` 和 `ThrottlesExceptionsWithRedis` 的构造函数也改为接受秒。

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

***

### 包

#### 服务提供者的发布

**影响度:非常低**

Laravel 11 新项目的 `config/app.php` 中不再有 `providers` 数组。包中要发布服务提供者时,请用 `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 不再自动加载迁移,请通过下面的命令发布迁移。

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

同时更新 `config/sanctum.php` 里的中间件配置。

```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`       | 高   | 发布迁移                               |
| Carbon 3             | 中   | 检查 `diffIn*` 的返回值                  |
| 秒级限流                 | 中   | 把 `decayMinutes` 改为 `decaySeconds` |
| 移除 Doctrine DBAL     | 低   | 迁移到原生 schema 方法                    |

***

## 参考资料

* [官方升级指南(英文)](https://laravel.com/docs/11.x/upgrade)
* [laravel/laravel 仓库的差异(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/blog/upgrade-9-to-10.md)
- [Laravel 11 升级到 12 指南](/zh/blog/upgrade-11-to-12.md)
- [Laravel 12 升级到 13 指南](/zh/blog/upgrade-12-to-13.md)
- [Laravel 8 升级到 9](/zh/blog/upgrade-8-to-9.md)
- [Laravel 11 之后的应用结构](/zh/advanced/app-structure.md)
