发行说明
版本化方案
Laravel 及官方发布的包皆遵循 语义化版本。主要的框架版本每年「2 月」发布,而次要的和补丁版本可能每周发布一次。次要版本和修补程序版本应 从不 包含非兼容性的更改。
你从应用或包中引用 Laravel 框架或其组件时,应始终使用版本约束,如 ^9.0
,因为 Laravel 的主要版本确实包含非兼容性更改。但是,我们努力确保您可以在一天或更短的时间内更新到新的主要版本。
命名参数
目前,PHP 的 命名参数 功能还没有被 Laravel 的向后兼容性 指南所涵盖。我们可以在必要时选择重命名函数参数,以改进 Laravel 代码库。因此,在调用 Laravel 方法时使用命名参数应该谨慎,并且要理解参数名将来可能会改变。
支持策略
对于所有 Laravel 发行版本,BUG 修复的期限为 18 个月,安全修复的期限为 2 年。对于包括 Lumen 在内的所有额外的库,只有最新的版本才会得到 BUG 修复。此外,请查阅 Laravel 支持的 数据库版本。
版本 | PHP (*) | 发行时间 | Bug 修复截止时间 | 安全修复截止时间 |
---|---|---|---|---|
6 (LTS) | 7.2 - 8.0 | 2019年9月3日 | 2022年1月25日 | 2022年9月6日 |
7 | 7.2 - 8.0 | 2020年3月3日 | 2020年10月6日 | 2021年3月3日 |
8 | 7.3 - 8.1 | 2020年9月8日 | 2022年7月26日 | 2023年1月24日 |
9 | 8.0 - 8.1 | 2022年2月8日 | 2023年8月8日 | 2024年2月8日 |
10 | 8.0 - 8.1 | 2023年2月7日 | 2024年8月7日 | 2025年2月7日 |
(*) 支持的PHP版本
Laravel 9
正如你所知,随着 Laravel 8 的发布,Laravel 已经过渡到了年度发布。以前,主要版本每6个月发布一次。这一转变旨在减轻社区的维护负担,并挑战我们的开发团队在不引入突破性更改的情况下提供惊人、强大的新功能。因此,我们在不破坏向后兼容性的情况下,向 Laravel 8 提供了各种强大的功能,例如并行测试支持、改进的 Breeze starter 工具包、HTTP 客户端改进,甚至还有新的 Eloquent 关联关系类型,例如oFMany
(一对多检索)。
因此,在当前版本中发布新功能的承诺可能会导致未来的「主要」版本主要用于「维护」任务,例如升级上游依赖项,这可以在这些发行说明中看到。
Laravel 9 延续了 Laravel 8.x 的改进通过引入对 Symfony 6.0 组件、Symfony Mailer、Flysystem 3.0、改进的 routes:list
输出、Laravel Scout 数据库驱动程序、新的 Eloquent 访问器 / 修改器语法、通过枚举的隐式路由绑定,以及其他各种错误修复和可用性改进。
PHP 8.0
Laravel 9.x 至少需要 PHP8.0.2。
Symfony Mailer
Symfony Mailer 的支持是由 Dries Vints, James Brooks, 和 Julius Kiekbusch.
Laravel 以前的版本使用了 Swift Mailer 库发送外发邮件。然而,该库已不再维护,由 Symfony Mailer 继承。
请查看 升级指南 以了解有关确保您的应用程序与 Symfony Mailer 兼容的更多信息。
Flysystem 3.x
Flysystem 3.x 的支持由 Dries Vints 提供。
Laravel 9.x 将我们上游的 Flysystem 依赖升级到 Flysystem 3.x。 Flysystem 为 Storage
门面提供的所有文件系统交互提供支持。
请查看 升级指南 以了解有关确保您的应用程序与 Flysystem 3.x 兼容的更多信息。
Eloquent 访问器/修改器 改进
改进的 Eloquent 访问器/修改器由 Taylor Otwell 贡献。
Laravel 9.x 提供了一种新的方式来定义 Eloquent 访问器和修改器。在以前的 Laravel 版本中,定义访问器和修改器的唯一方法是在模型上定义前缀方法 ,如下所示:
public function getNameAttribute($value)
{
return strtoupper($value);
}
public function setNameAttribute($value)
{
$this->attributes['name'] = $value;
}
然而,在 Laravel 9.x 中,你可以使用一个不带前缀的方法定义访问器和修改器,该方法的返回类型是Illuminate\Database\Eloquent\Casts\Attribute
:
use Illuminate\Database\Eloquent\Casts\Attribute;
public function name(): Attribute
{
return new Attribute(
get: fn ($value) => strtoupper($value),
set: fn ($value) => $value,
);
}
此外,这种定义访问器的新方法将缓存由属性返回的对象值,就像 自定义转换类:
use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;
public function address(): Attribute
{
return new Attribute(
get: fn ($value, $attributes) => new Address(
$attributes['address_line_one'],
$attributes['address_line_two'],
),
set: fn (Address $value) => [
'address_line_one' => $value->lineOne,
'address_line_two' => $value->lineTwo,
],
);
}
Enum Eloquent 属性转换
注意:枚举转换仅适用于 PHP 8.1+。
枚举转换由 Mohamed Said 贡献。
Eloquent 现在允许您将属性值转换为 PHP "backed" enums。 为此,您可以在模型的 $casts
属性数组中指定要转换的属性和枚举:
use App\Enums\ServerStatus;
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'status' => ServerStatus::class,
];
一旦你在你的模型上定义了转换,当你与属性交互时,指定的属性将自动转换为枚举:
if ($server->status == ServerStatus::provisioned) {
$server->status = ServerStatus::ready;
$server->save();
}
使用枚举的隐式路由绑定
隐式路由绑定由 Nuno Maduro贡献。
PHP 8.1 引入了对 Enums 的支持。 Laravel 9.x 引入了在路由定义中键入提示 Enum 的能力,并且 Laravel 只会在该路由段是 URI 中的有效 Enum 值时调用该路由。 否则,将自动返回 HTTP 404 响应。 例如,给定以下枚举:
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}
你可以定义一个只有在 {category}
路由段是 fruits
或 people
时才会被调用的路由。 否则,将返回 HTTP 404 响应:
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});
路由绑定的强制作用域
路由绑定的强制作用域由 Claudio Dekker贡献.
在之前的 Laravel 版本中,您可能希望在路由定义中限定第二个 Eloquent 模型,使其必须是之前 Eloquent 模型的子模型。 例如,考虑这个通过 slug 为特定用户检索博客文章的路由定义:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});
当使用自定义键控隐式绑定作为嵌套路由参数时,Laravel 将自动限定查询范围以通过其父级检索嵌套模型,使用约定来猜测父级上的关系名称。 但是,当自定义键用于子路由绑定时,Laravel 之前仅支持此行为。
然而,在 Laravel 9.x 中,即使没有提供自定义键,你现在也可以指示 Laravel 限定“子”绑定。 为此,您可以在定义路由时调用 scopeBindings
方法:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
})->scopeBindings();
或者,您可以指示整个路由定义组使用范围绑定:
Route::scopeBindings()->group(function () {
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
});
});