# 发行说明
## 版本控制方案
Laravel 的版本控制方案使用以下约定:`主版本号.次版本号.修订号`。 次版本号框架每六个月(二月和八月)发布,而修订号版本可能每周发布一次,修订号版本**不**包含重大更改。
当你从应用程序中或在包中引用 Laravel 框架或者其他组件时,应该始终使用版本约束,例如`5.7.*`,因为 Laravel 的次要版本包含重大更改。但是,我们会努力确保你可以在一天或者更短时间内完成更新。
主版本之间的发布往往需要很多年,每次发布代表框架架构和底层结构发生了根本的改变。而目前并没有准备开发主版本号的计划。
## 支持策略
对于 LTS 版本,例如 Laravel 5.5,提供两年的错误修复和三年的安全修复。这些版本提供最长时间的支持和维护。对于一般版本,则只是提供六个月的错误修复和一年的安全修复。
| 版本 | 发布时间 | Bug 修复截止时间 | 安全修复截止时间 |
| --- | --- | --- | --- |
| 5.0 | 2015年2月4日 | 2015年8月4日 | 2016年2月4日 |
| 5.1 (LTS) | 2015年6月9日 | 2017年6月9日 | 2018年6月9日 |
| 5.2 | 2015年12月21日 | 2016年6月21日 | 2016年12月21日 |
| 5.3 | 2016年8月23日 | 2017年2月23日 | 2017年8月23日 |
| 5.4 | 2017年1月24日 | 2017年7月24日 | 2018年1月24日 |
| 5.5 (LTS) | 2017年8月30日 | 2019年8月30日 | 2020年8月30日 |
| 5.6 | 2018年2月7日 | 2018年8月7日 | 2019年2月7日 |
| 5.7 | 2018年8月 | 2019年2月 | 2019年8月 |
## Laravel 5.7
Laravel 5.7 继续在 Laravel 5.6 的基础上进行继续改进:「[Laravel Nova](https://nova.laravel.com/)」,可选的邮件认证到认证脚手架, 在授权和策略中对未登录用户的支持,控制台测试的改进,Symfony`dump-server`的集成,可定位的通知,还有各类其他 bug 修复和可用性改进。
### Laravel Nova
[Laravel Nova](https://nova.laravel.com/)是一个基于Laravel应用程序的漂亮的,同类产品中最佳的管理仪表板。 当然,Nova 的主要功能是使用 Eloquent 管理底层数据库记录。 此外,Nova 还提供对过滤器,镜头,行为,队列操作,指标,授权,自定义工具,自定义卡片,自定义字段等更多支持。
要了解有关 Laravel Nova 的更多信息,请查看[Nova 网站](https://nova.laravel.com/).
### 邮箱验证
Laravel5.7 为框架中包含身份验证的脚手架提供了可选的电子邮件验证。为了适应该特性,已经将`email_verified_at`时间戳字段添加到框架默认的`users`表的迁移文件中。
为了提示新注册的用户验证他们的邮件,`User`模型应该实现`MustVerifyEmail`接口:
~~~php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements MustVerifyEmail
{
// ...
}
~~~
一旦`User`模型实现`MustVerifyEmail`接口,新注册的用户将收到一封包含签名验证链接的电子邮件。点击此链接后,Laravel 将自动在数据库中记录验证时间,并将用户跳转到你刚才的页面。
`verified`中间件默认添加的应用程序的 HTTP 内核中。这个中间件可以添加到只允许通过验证的用户的路由:
~~~php
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
~~~
> {tip} 想了解有关电子邮件验证的详情,请查看[完整文档](https://laravel-china.org/docs/laravel/5.7/verification)。
### 访客 入口 / 策略
在以前版本的 Laravel 中,授权入口和策略字段为您的应用程序验证未授权的访客并返回`false`。现在,你可以通过声明"可选"类型提示或为用户参数定义提供`null`默认值来允许访客通过授权检查:
~~~php
Gate::define('update-post', function (?User $user, Post $post) {
// ...
});
~~~
### Symfony Dump Server
Laravel5.7 通过[a package by Marcel Pociot](https://github.com/beyondcode/laravel-dump-server)提供 Symfony 的`dump-server`命令集成。运行`dump-server`的 Artisan 命令来启动:
~~~php
php artisan dump-server
~~~
一旦服务启动,所有对`dump`命令的调用只会显示的`dump-server`控制台窗口,而不是浏览器中,以提供在不破坏 HTTP 响应输出的情况下检查数据。
### 通知本地化
Laravel 现在可以使用当前语言环境之外的语言发送通知,如果通知是在队列化状态下发送的话,它甚至可以记住这个语言环境。
为了实现这个功能,`Illuminate\Notifications\Notification`类目前提供了一个`locale`方法来设置所需的语言。在格式化通知时,应用程序会将语言环境设置为此语言,格式化完毕之后恢复为之前的:
~~~php
$user->notify((new InvoicePaid($invoice))->locale('es'));
~~~
多通知条目的本地化也可通过`Notification`facade 实现:
~~~php
Notification::locale('es')->send($users, new InvoicePaid($invoice));
~~~
### 控制台测试
Laravel 5.7 可使用`expectsQuestion`方法轻松模拟用户的控制台输入。此外,你也可以通过`assertExitCode`和`expectsOutput`方法来指定退出代码和期望输出的文本。 例如,考量如下控制台命令代码:
~~~php
Artisan::command('question', function () {
$name = $this->ask('What is your name?');
$language = $this->choice('Which language do you program in?', [
'PHP',
'Ruby',
'Python',
]);
$this->line('Your name is '.$name.' and you program in '.$language.'.');
});
~~~
可以使用如下带有`expectsQuestion`,`expectsOutput`,还有`assertExitCode`方法的测试用例,来测试上述控制台命令:
~~~php
/**
* Test a console command.
*
* @return void
*/
public function test_console_command()
{
$this->artisan('laracon')
->expectsQuestion('What is your name?', 'Taylor Otwell')
->expectsQuestion('Which language do you program in?', 'PHP')
->expectsOutput('Your name is Taylor Otwell and you program in PHP.')
->assertExitCode(0);
}
~~~
### URL 生成器 & 回调语法
在给定控制器生成 URL 行为时,Laravel 的 URL 生成器不仅可以支持字符串传值形式,现在也可支持「回调」的语法了 :
~~~php
action([UserController::class, 'index']);
~~~
### 分页器链接
Laravel 5.7 可以自由控制在分页器的 URL「窗口」添加多少个链接。默认在主分页链接的两侧各有三个链接。但是,你可以使用`onEachSide`方法来控制这个数量:
~~~php
{{ $paginator->onEachSide(5)->links() }}
~~~
### 文件系统的读/写流
Laravel 的文件系统这次提供了`readStream`和`writeStream`方法:
~~~php
Storage::disk('s3')->writeStream(
'remote-file.zip',
Storage::disk('local')->readStream('local-file.zip')
);
~~~