升级指南
升级指南
高影响变化
中影响变化
从 7.x 升级到 8.0
预计升级时间:15分钟
注意:我们试图记录所有可能的重大更改。由于其中一些重大更改是框架中晦涩难懂的部分,因此这些更改中只有一部分实际上可能会影响您的应用程序。
PHP 7.3.0 要求
影响的程度:中
Laravel 8 需要 PHP 7.3.0 或以上。
更新依赖
请更新你 composer.json
文件中以下依赖:
guzzlehttp/guzzle
to^7.0.1
facade/ignition
to^2.3.6
laravel/framework
to^8.0
laravel/ui
to^3.0
nunomaduro/collision
to^5.0
phpunit/phpunit
to^9.0
下列官方扩展包已发布对应新版本以适配 Laravel 8。如有需要,请阅读对应的更新说明进行升级:
此外,Laravel安装程序已更新,以支持 composer create-project
和 Laravel Jetstream。 所有低于 4.0 的安装程序将在2020年10月之后停止工作。您应尽快将全局安装程序升级到 ^4.0
。
最后,检查应用中的其他第三方依赖包,确保你使用的是适用于 Laravel 8 的版本。
集合
<code>isset</code> 方法
影响的程度:低
为了和经典的 PHP 保持一致,Illuminate\Support\Collection
的 offsetExists
方法中的 array_key_exists
已经替换成了 isset
。由于这一变化,在处理包含 null
值的集合时,会和以前不同:
$collection = collect([null]);
// Laravel 7.x - true
isset($collection[0]);
// Laravel 8.x - false
isset($collection[0]);
数据库
Seeder & Factory 命名空间
影响的程度:高
Seeders 和 factories 已拥有命名空间。你需要在 seeder 类内添加 Database\Seeders
的命名空间。此外,database/seeds
应该重命名为 database/seeders
:
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
...
}
}
如果你使用的是 laravel/legacy-factories
包,无需改动。但是,如果你是升级工厂类,则需要将 Database\Factories
命名空间添加到这些类内。
然后,将 composer.json
文件中 autoload
部分的 classmap
移除,添加以下新的命名空间和目录映射关系:
"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 来安装这个扩展包:
composer require laravel/legacy-factories
<code>Castable</code> 接口
影响程度:低
Castable
接口的 castUsing
方法已经更新,它将接受一个数组形式的参数,如果您实现了这个接口,相应的,您应该更新你的实现:
public static function castUsing(array $arguments);
Increment / Decrement 事件
影响程度:低
现在,Eloquent 模型实例的 increment
或 decrement
方法调用时,,会触发相关模型的「update」和「save」事件。
事件
<code>EventServiceProvider</code> 类
影响程度:低
如果您的 App\Providers\EventServiceProvider
类包含了 register
方法,您应确保在该方法的开始处调用 parent::register
方法。否则,您的应用事件将不会被注册。
<code>Dispatcher</code> 契约
影响程度:低
Illuminate\Contracts\Events\Dispatcher
契约的 listen
方法的 $listener
参数修改为可选的。这一改动是为了通过反射自动检测处理事件类型。如果您手动实现了这个接口,您应该相应的更新您的实现:
public function listen($events, $listener = null);
框架
维护模式更新
影响程度:可选
维护模式 功能在 Laravel 8.x 中进行了改进。现已支持预渲染维护模式模板,并且消除了用户在维护模式期间遇到错误的机会。然而,为了支持这一特性,您必须将下方代码添加到 public/index.php
文件中。这些代码应当置于现有的 LARAVEL_START
常量定义下:
define('LARAVEL_START', microtime(true));
if (file_exists(__DIR__.'/../storage/framework/maintenance.php')) {
require __DIR__.'/../storage/framework/maintenance.php';
}
<code>php artisan down --message</code> 选项
影响程度:中
php artisan down
的 --message
选项已经移除。取而代之的,您可以使用 预渲染维护模式模板 来包含您的维护模式消息。
<code>php artisan serve --no-reload</code> 选项
影响程度:中
php artisan serve
命令新增了 --no-reload
选项。这将指示内置服务器在检测到环境文件更改时不要重新加载。当在 CI 环境中运行 Laravel Dusk测试,这个特性是非常有用的。
管理 <code>$app</code> 属性
影响程度:低
之前不推荐使用的 Illuminate\Support\Manager
类中 $app
属性已经被移除了。如果您依赖这个属性,您应当使用 $container
属性来代替。
<code>elixir</code> 助手方法
影响程度:低
之前不推荐使用的 elixir
助手方法已经移除。如果您的应用仍使用这个方法,推荐您升级至 Laravel Mix 。
邮件
<code>sendNow</code> 方法
影响程度:低
之前不推荐使用的 sendNow
方法已经移除,请使用 send
方法来代替之。
分页
分页默认值
影响程度:高
分页器现在使用 Tailwind CSS framework 作为其默认样式。若要继续使用 Bootstrap ,您应当在应用的 AppServiceProvider
的 boot
方法中添加如下调用:
use Illuminate\Pagination\Paginator;
Paginator::useBootstrap();
队列
<code>retryAfter</code> 方法
影响程度:高
为了和 Laravel 的其他功能保持一致,队列任务,邮件系统,通知和监听器中的 retryAfter
方法和 retryAfter
属性已经重命名为 backoff
。你应该修改你应用中相关的方法和属性名称。
<code>timeoutAt</code> 属性
影响程度:高
队列任务,通知和监听器的 timeoutAt
属性已经重命名为 retryUntil
。你应该修改你应用中相关的属性名称。
<code>allOnQueue()</code> 、 <code>allOnConnection()</code> 方法
影响程度:高
为了和其他调度方法保持一致,与任务链一起使用的 allOnQueue()
和 allOnConnection()
方法已经移除。您可以使用 onQueue()
和 onConnection()
方法代替之。它们应当在调用 dispatch
方法前调用:
ProcessPodcast::withChain([
new OptimizePodcast,
new ReleasePodcast
])->onConnection('redis')->onQueue('podcasts')->dispatch();
请注意,这个改变仅影响使用 withChain
方法的代码。在使用全局助手方法 dispatch()
时,allOnQueue()
和 allOnConnection()
方法依然可用。
失败任务表批处理支持
影响程度:可选
如果您想在 Laravel 8.x 中使用 job batching 功能,您需要更新您的 failed_jobs
数据库表。首先,您应当添加一个新的 uuid
字段到表中:
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 :
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
类包含了一个 $namespace
属性,其值为 App\Http\Controllers
。在例如调用 action
助手方法的时候,这个属性的值用于自动为控制器路由声明和控制器路由 URL 添加前缀。
在 Laravel 8 ,这个属性默认被置为 null
。这个特性允许您的控制器路由声明使用标准的 PHP callable 语法,在许多 IDE 中,它更好地提供了跳转控制器的支持:
use App\Http\Controllers\UserController;
// Using PHP callable syntax...
Route::get('/users', [UserController::class, 'index']);
// Using string syntax...
Route::get('/users', 'App\Http\Controllers\UserController@index');
多数情况下,它不会影响正在升级的应用,因为 RouteServiceProvider
中依然包含了 $namespace
属性及其之前的值。当然,如果您通过创建一个全新的 Laravel 项目来升级您的应用,你可能会遇到这种突变。
如果您想要继续使用之前的自动添加控制器路由前缀的特性,只需设置 RouteServiceProvider
中的 $namespace
属性的值并且在 boot
方法中使用 $namespace
属性更新您的路由注册:
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());
});
}
}
调度
<code>cron-expression</code> 库
影响程度:低
Laravel 的 dragonmantank/cron-expression
依赖包已经从 2.x
更新至 3.x
。这不会给您的应用造成任何影响,除非您直接操作了 cron expression
库。如果您直接操作了它,请参阅它的 更新日志。
会话
<code>Session</code> 契约
影响程度:低
Illuminate\Contracts\Session\Session
契约新增一个新的 pull
方法。如果您手动实现了这个契约,您应当像下面这样更新你的实现:
/**
* 获取指定键的值,然后遗忘之
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function pull($key, $default = null);
测试
<code>decodeResponseJson</code> 方法
影响程度:低
属于 Illuminate\Testing\TestResponse
类的 decodeResponseJson
方法不再接受任何参数。请考虑使用 json
方法代替之。
<code>assertExactJson</code> 方法
影响程度:中
assertExactJson
方法现在需要一个被比较的数组的数值键,并且与之拥有相同的顺序。如果您想要将 JSON 与数组进行对比,并且不要求数值键有相同的顺序,您可以使用 assertSimilarJson
方法来代替之。
验证
数据库规则连接
影响程度:低
现在,当处理查询时,unique
和 exists
规则将遵循 Eloquent 模型指定的连接名(通过模型的 getConnectionName
方法访问)。
其他
我们推荐您查看 laravel/laravel
的 GitHub 仓库 上的更新日志。尽管许多更新不是必须的,但您可能希望将这些文件与您的应用保持一致。其中一些更新已经包含在这个升级说明中了,但是其他的,诸如配置文件或注释的更改可能没有。您可以借助 GitHub comparison tool 工具来很方便的浏览变更,以便选择那些对你而言更为重要的更新。