Skip to content

升级指南

高影响变更

中等影响变更

从 7.x 升级到 8.0

预计升级时间:15 分钟

exclamation

我们尝试记录每一个可能的重大变更。由于这些变更中的一些位于框架的偏僻部分,只有一部分变更可能实际影响到您的应用程序。

需要 PHP 7.3.0

影响可能性:中等

新的最低 PHP 版本现在是 7.3.0。

更新依赖

在您的 composer.json 文件中更新以下依赖:

  • guzzlehttp/guzzle^7.0.1
  • facade/ignition^2.3.6
  • laravel/framework^8.0
  • laravel/ui^3.0
  • nunomaduro/collision^5.0
  • phpunit/phpunit^9.0

以下第一方包有新的主要版本以支持 Laravel 8。如果适用,您应该在升级前阅读它们各自的升级指南:

此外,Laravel 安装器已更新以支持 composer create-project 和 Laravel Jetstream。任何低于 4.0 的安装器将在 2020 年 10 月后停止工作。您应尽快将全局安装器升级到 ^4.0

最后,检查您的应用程序使用的任何其他第三方包,并验证您使用的是支持 Laravel 8 的正确版本。

集合

isset 方法

影响可能性:低

为了与典型的 PHP 行为保持一致,Illuminate\Support\CollectionoffsetExists 方法已更新为使用 isset 而不是 array_key_exists。这可能会在处理值为 null 的集合项时导致行为变化:

php
$collection = collect([null]);

// Laravel 7.x - true
isset($collection[0]);

// Laravel 8.x - false
isset($collection[0]);

数据库

Seeder 和 Factory 命名空间

影响可能性:高

Seeders 和 factories 现在有命名空间。为了适应这些变化,请将 Database\Seeders 命名空间添加到您的 seeder 类中。此外,之前的 database/seeds 目录应重命名为 database/seeders

php
<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * 为应用程序的数据库填充数据。
     *
     * @return void
     */
    public function run()
    {
        ...
    }
}

如果您选择使用 laravel/legacy-factories 包,则不需要对您的 factory 类进行更改。但是,如果您正在升级您的 factories,您应该将 Database\Factories 命名空间添加到这些类中。

接下来,在您的 composer.json 文件中,从 autoload 部分中删除 classmap 块,并添加新的命名空间类目录映射:

php
"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Database\\Factories\\": "database/factories/",
        "Database\\Seeders\\": "database/seeders/"
    }
},

Eloquent

模型工厂

影响可能性:高

Laravel 的 模型工厂 功能已被完全重写以支持类,并且与 Laravel 7.x 风格的工厂不兼容。然而,为了简化升级过程,创建了一个新的 laravel/legacy-factories 包,以便在 Laravel 8.x 中继续使用现有的工厂。您可以通过 Composer 安装此包:

php
composer require laravel/legacy-factories

Castable 接口

影响可能性:低

Castable 接口的 castUsing 方法已更新为接受一个参数数组。如果您正在实现此接口,您应该相应地更新您的实现:

php
public static function castUsing(array $arguments);

增量/减量事件

影响可能性:低

在 Eloquent 模型实例上执行 incrementdecrement 方法时,现在将触发适当的“更新”和“保存”相关的模型事件。

事件

EventServiceProvider

影响可能性:低

如果您的 App\Providers\EventServiceProvider 类包含一个 register 函数,您应该确保在此方法的开头调用 parent::register。否则,您的应用程序的事件将不会被注册。

Dispatcher 合约

影响可能性:低

Illuminate\Contracts\Events\Dispatcher 合约的 listen 方法已更新,使 $listener 属性可选。此更改是为了支持通过反射自动检测处理的事件类型。如果您正在手动实现此接口,您应该相应地更新您的实现:

php
public function listen($events, $listener = null);

框架

维护模式更新

影响可能性:可选

Laravel 8.x 的 维护模式 功能已得到改进。现在支持预渲染维护模式模板,消除了最终用户在维护模式期间遇到错误的可能性。然而,为了支持这一点,必须将以下行添加到您的 public/index.php 文件中。这些行应直接放在现有的 LARAVEL_START 常量定义下:

php
define('LARAVEL_START', microtime(true));

if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
    require $maintenance;
}

php artisan down --message 选项

影响可能性:中等

php artisan down 命令的 --message 选项已被移除。作为替代方案,请考虑使用您选择的消息 预渲染您的维护模式视图

php artisan serve --no-reload 选项

影响可能性:低

php artisan serve 命令中添加了一个 --no-reload 选项。这将指示内置服务器在检测到环境文件更改时不重新加载服务器。此选项主要在 CI 环境中运行 Laravel Dusk 测试时有用。

Manager $app 属性

影响可能性:低

Illuminate\Support\Manager 类中先前已弃用的 $app 属性已被移除。如果您依赖此属性,您应该使用 $container 属性。

elixir 助手

影响可能性:低

先前已弃用的 elixir 助手已被移除。仍在使用此方法的应用程序建议升级到 Laravel Mix

邮件

sendNow 方法

影响可能性:低

先前已弃用的 sendNow 方法已被移除。请改用 send 方法。

分页

分页默认值

影响可能性:高

分页器现在使用 Tailwind CSS 框架 作为其默认样式。为了继续使用 Bootstrap,您应该在应用程序的 AppServiceProviderboot 方法中添加以下方法调用:

php
use Illuminate\Pagination\Paginator;

Paginator::useBootstrap();

队列

retryAfter 方法

影响可能性:高

为了与 Laravel 的其他功能保持一致,队列作业、邮件、通知和监听器的 retryAfter 方法和 retryAfter 属性已重命名为 backoff。您应该在应用程序的相关类中更新此方法/属性的名称。

timeoutAt 属性

影响可能性:高

队列作业、通知和监听器的 timeoutAt 属性已重命名为 retryUntil。您应该在应用程序的相关类中更新此属性的名称。

allOnQueue() / allOnConnection() 方法

影响可能性:高

为了与其他调度方法保持一致,使用作业链的 allOnQueue()allOnConnection() 方法已被移除。您可以使用 onQueue()onConnection() 方法代替。这些方法应在调用 dispatch 方法之前调用:

php
ProcessPodcast::withChain([
    new OptimizePodcast,
    new ReleasePodcast
])->onConnection('redis')->onQueue('podcasts')->dispatch();

请注意,此更改仅影响使用 withChain 方法的代码。使用全局 dispatch() 助手时,allOnQueue()allOnConnection() 仍然可用。

失败作业表批处理支持

影响可能性:可选

如果您计划使用 Laravel 8.x 的 作业批处理 功能,您的 failed_jobs 数据库表需要更新。首先,应在您的表中添加一个新的 uuid 列:

php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('failed_jobs', function (Blueprint $table) {
    $table->string('uuid')->after('id')->nullable()->unique();
});

接下来,您的 queue 配置文件中的 failed.driver 配置选项应更新为 database-uuids

此外,您可能希望为现有的失败作业生成 UUID:

php
DB::table('failed_jobs')->whereNull('uuid')->cursor()->each(function ($job) {
    DB::table('failed_jobs')
        ->where('id', $job->id)
        ->update(['uuid' => (string) Illuminate\Support\Str::uuid()]);
});

路由

自动控制器命名空间前缀

影响可能性:可选

在 Laravel 的先前版本中,RouteServiceProvider 类包含一个值为 App\Http\Controllers$namespace 属性。此属性的值用于自动为控制器路由声明和控制器路由 URL 生成添加前缀,例如在调用 action 助手时。

在 Laravel 8 中,此属性默认设置为 null。这允许您的控制器路由声明使用标准的 PHP 可调用语法,这为许多 IDE 提供了更好的跳转到控制器类的支持:

php
use App\Http\Controllers\UserController;

// 使用 PHP 可调用语法...
Route::get('/users', [UserController::class, 'index']);

// 使用字符串语法...
Route::get('/users', 'App\Http\Controllers\UserController@index');

在大多数情况下,这不会影响正在升级的应用程序,因为您的 RouteServiceProvider 仍将包含具有其先前值的 $namespace 属性。然而,如果您通过创建一个全新的 Laravel 项目来升级您的应用程序,您可能会遇到此破坏性更改。

如果您希望继续使用原始的自动前缀控制器路由,您可以简单地在您的 RouteServiceProvider 中设置 $namespace 属性的值,并更新 boot 方法中的路由注册以使用 $namespace 属性:

php
class RouteServiceProvider extends ServiceProvider
{
    /**
     * 应用程序的“home”路由的路径。
     *
     * 这用于 Laravel 认证在登录后重定向用户。
     *
     * @var string
     */
    public const HOME = '/home';

    /**
     * 如果指定,此命名空间将自动应用于您的控制器路由。
     *
     * 此外,它被设置为 URL 生成器的根命名空间。
     *
     * @var string
     */
    protected $namespace = 'App\Http\Controllers';

    /**
     * 定义您的路由模型绑定、模式过滤器等。
     *
     * @return void
     */
    public function boot()
    {
        $this->configureRateLimiting();

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

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

    /**
     * 为应用程序配置速率限制器。
     *
     * @return void
     */
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
        });
    }
}

调度

cron-expression

影响可能性:低

Laravel 对 dragonmantank/cron-expression 的依赖已从 2.x 更新到 3.x。这不应在您的应用程序中造成任何破坏性更改,除非您直接与 cron-expression 库交互。如果您直接与此库交互,请查看其 变更日志

会话

Session 合约

影响可能性:低

Illuminate\Contracts\Session\Session 合约已接收一个新的 pull 方法。如果您正在手动实现此合约,您应该相应地更新您的实现:

php
/**
 * 获取给定键的值,然后忘记它。
 *
 * @param  string  $key
 * @param  mixed  $default
 * @return mixed
 */
public function pull($key, $default = null);

测试

decodeResponseJson 方法

影响可能性:低

属于 Illuminate\Testing\TestResponse 类的 decodeResponseJson 方法不再接受任何参数。请考虑使用 json 方法代替。

assertExactJson 方法

影响可能性:中等

assertExactJson 方法现在要求比较数组的数字键匹配并且顺序相同。如果您希望在不要求数字键数组顺序相同的情况下将 JSON 与数组进行比较,您可以使用 assertSimilarJson 方法。

验证

数据库规则连接

影响可能性:低

uniqueexists 规则现在将在执行查询时尊重 Eloquent 模型的指定连接名称(通过模型的 getConnectionName 方法访问)。

杂项

我们还鼓励您查看 laravel/laravel GitHub 仓库 中的更改。虽然这些更改中的许多不是必需的,但您可能希望将这些文件与您的应用程序保持同步。这些更改中的一些将在本升级指南中介绍,但其他更改,例如配置文件或注释的更改,将不会介绍。您可以使用 GitHub 比较工具 轻松查看更改,并选择哪些更新对您来说是重要的。