Skip to content
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

升级指南 ​

从 5.3 升级到 5.4.0 ​

预计升级时间:1-2 小时 ​

注意

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

更新依赖项 ​

在您的 composer.json 文件中将 laravel/framework 依赖项更新为 5.4.*。此外,您还应该将 phpunit/phpunit 依赖项更新为 ~5.7。

删除已编译的服务文件 ​

如果存在,您可以删除 bootstrap/cache/compiled.php 文件。框架不再使用它。

清除缓存 ​

在升级所有包之后,您应该运行 php artisan view:clear 以避免与 Illuminate\View\Factory::getFirstLoop() 删除相关的 Blade 错误。此外,您可能需要运行 php artisan route:clear 以清除路由缓存。

Laravel Cashier ​

Laravel Cashier 已经与 Laravel 5.4 兼容。

Laravel Passport ​

Laravel Passport 2.0.0 已发布,以提供与 Laravel 5.4 和 Axios JavaScript 库的兼容性。如果您从 Laravel 5.3 升级并使用预构建的 Passport Vue 组件,您应该确保 Axios 库在您的应用程序中全局可用为 axios。

Laravel Scout ​

Laravel Scout 3.0.0 已发布,以提供与 Laravel 5.4 的兼容性。

Laravel Socialite ​

Laravel Socialite 3.0.0 已发布,以提供与 Laravel 5.4 的兼容性。

Laravel Tinker ​

为了继续使用 tinker Artisan 命令,您还应该安装 laravel/tinker 包:

php
composer require laravel/tinker

安装包后,您应该将 Laravel\Tinker\TinkerServiceProvider::class 添加到 config/app.php 配置文件中的 providers 数组中。

Guzzle ​

Laravel 5.4 需要 Guzzle 6.0 或更高版本。

授权 ​

getPolicyFor 方法 ​

以前,当调用 Gate::getPolicyFor($class) 方法时,如果找不到策略,会抛出异常。现在,如果找不到给定类的策略,该方法将返回 null。如果您直接调用此方法,请确保重构代码以检查 null:

php
$policy = Gate::getPolicyFor($class);

if ($policy) {
    // 以前在 try 块中的代码
} else {
    // 以前在 catch 块中的代码
}

Blade ​

@section 转义 ​

在 Laravel 5.4 中,传递给 section 的内联内容会自动转义:

php
@section('title', $content)

如果您希望在 section 中呈现未转义的内容,您必须使用传统的“长格式”样式声明 section:

php
@section('title')
    {!! $content !!}
@stop

启动器 ​

如果您手动覆盖 HTTP 或控制台内核上的 $bootstrappers 数组,您应该将 DetectEnvironment 条目重命名为 LoadEnvironmentVariables 并删除 ConfigureLogging。

广播 ​

通道模型绑定 ​

在 Laravel 5.3 中定义通道名称占位符时,使用 * 字符。在 Laravel 5.4 中,您应该使用 {foo} 样式占位符定义这些占位符,如路由:

php
Broadcast::channel('App.User.{userId}', function ($user, $userId) {
    return (int) $user->id === (int) $userId;
});

集合 ​

every 方法 ​

every 方法的行为已移至 nth 方法,以匹配 Lodash 定义的方法名称。

random 方法 ​

调用 $collection->random(1) 现在将返回一个包含一个项目的新集合实例。以前,这会返回一个单一对象。此方法仅在不提供参数时返回单一对象。

容器 ​

通过 bind / instance 进行别名 ​

在以前的 Laravel 版本中,您可以将数组作为第一个参数传递给 bind 或 instance 方法来注册别名:

php
$container->bind(['foo' => FooContract::class], function () {
    return 'foo';
});

然而,这种行为在 Laravel 5.4 中已被移除。要注册别名,您现在应该使用 alias 方法:

php
$container->alias(FooContract::class, 'foo');

带前导斜杠的绑定类 ​

不再支持将带前导斜杠的类绑定到容器中。此功能需要在容器内进行大量字符串格式化调用。相反,只需在没有前导斜杠的情况下注册您的绑定:

php
$container->bind('Class\Name', function () {
    //
});

$container->bind(ClassName::class, function () {
    //
});

make 方法参数 ​

容器的 make 方法不再接受第二个参数数组。此功能通常表示代码味道。通常,您总是可以以更直观的方式构造对象。

如果必须继续传递参数数组,您可以使用 makeWith 方法。

解析回调 ​

容器的 resolving 和 afterResolving 方法现在必须提供类名或绑定键作为方法的第一个参数:

php
$container->resolving('Class\Name', function ($instance) {
    //
});

$container->afterResolving('Class\Name', function ($instance) {
    //
});

share 方法已移除 ​

share 方法已从容器中移除。这是一个遗留方法,已经有几年没有被记录。如果您正在使用此方法,您应该开始使用 singleton 方法:

php
$container->singleton('foo', function () {
    return 'foo';
});

控制台 ​

Illuminate\Console\AppNamespaceDetectorTrait Trait ​

如果您直接引用 Illuminate\Console\AppNamespaceDetectorTrait trait,请更新您的代码以引用 Illuminate\Console\DetectsApplicationNamespace。

数据库 ​

orWhere 的数组参数 ​

当将数组作为第一个参数传递给 orWhere 方法时,内部条件现在在每个数组元素之间使用 OR:

php
$query->orWhere(['a' => 1, 'b' => 2])

OR (a = 1 AND b = 2) // 以前的行为...

OR (a = 1 OR b = 2) // 新行为...

自定义连接 ​

如果您以前为 db.connection.{driver-name} 键绑定服务容器绑定以解析自定义数据库连接实例,您现在应该在 AppServiceProvider 的 register 方法中使用 Illuminate\Database\Connection::resolverFor 方法:

php
use Illuminate\Database\Connection;

Connection::resolverFor('driver-name', function ($connection, $database, $prefix, $config) {
    //
});

获取模式 ​

Laravel 不再包括从配置文件中自定义 PDO “获取模式”的功能。相反,始终使用 PDO::FETCH_OBJ。如果您仍然希望为您的应用程序自定义获取模式,您可以监听新的 Illuminate\Database\Events\StatementPrepared 事件:

php
Event::listen(StatementPrepared::class, function ($event) {
    $event->statement->setFetchMode(...);
});

Eloquent ​

日期转换 ​

date 转换现在将列转换为 Carbon 对象并调用对象上的 startOfDay 方法。如果您希望保留日期的时间部分,您应该使用 datetime 转换。

外键约定 ​

如果在定义关系时未显式指定外键,Eloquent 现在将使用相关模型的表名和主键名来构建外键。对于绝大多数应用程序,这不是行为的变化。例如:

php
public function user()
{
    return $this->belongsTo(User::class);
}

就像以前的 Laravel 版本一样,这种关系通常会使用 user_id 作为外键。然而,如果您覆盖了 User 模型的 $primaryKey 属性或 getKeyName 方法,行为可能与以前的版本不同。例如:

php
public function getKeyName()
{
    return 'key';
}

在这种情况下,Laravel 现在将尊重您的自定义并确定外键列名为 user_key 而不是 user_id。

BelongsToMany setJoin ​

setJoin 方法已重命名为 performJoin。

BelongsToMany getRelatedIds ​

getRelatedIds 方法已重命名为 allRelatedIds。

Has One / Many createMany ​

hasOne 或 hasMany 关系的 createMany 方法现在返回一个集合对象而不是数组。

Has One / Many getPlainForeignKey ​

getPlainForeignKey 方法已重命名为 getForeignKeyName。

相关模型连接 ​

相关模型现在将使用与父模型相同的连接。例如,如果您执行如下查询:

php
User::on('example')->with('posts');

Eloquent 将在 example 连接上查询 posts 表而不是默认数据库连接。如果您希望从默认连接读取 posts 关系,您应该显式将模型的连接设置为应用程序的默认连接。

chunk 方法 ​

查询构建器 chunk 方法现在需要一个 orderBy 子句,这为 each 方法提供了一致性。如果未提供 orderBy 子句,将抛出异常。例如:

php
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
    foreach ($users as $user) {
        //
    }
});

Eloquent 查询构建器 chunk 方法将在模型的主键上自动应用 orderBy 子句,如果未提供。

create 和 forceCreate 方法 ​

Model::create 和 Model::forceCreate 方法已移至 Illuminate\Database\Eloquent\Builder 类,以便更好地支持在多个连接上创建模型。然而,如果您在自己的模型中扩展这些方法,您将需要修改您的实现以在构建器上调用 create 方法。例如:

php
public static function create(array $attributes = [])
{
    $model = static::query()->create($attributes);

    // ...

    return $model;
}

hydrate 方法 ​

如果您当前正在将自定义连接名称传递给此方法,您现在应该使用 on 方法:

php
User::on('connection')->hydrate($records);

hydrateRaw 方法 ​

Model::hydrateRaw 方法已重命名为 fromQuery。如果您将自定义连接名称传递给此方法,您现在应该使用 on 方法:

php
User::on('connection')->fromQuery('...');

whereKey 方法 ​

whereKey($id) 方法现在将为给定的主键值添加一个“where”子句。以前,这会进入动态“where”子句构建器并为“key”列添加一个“where”子句。如果您使用 whereKey 方法动态添加 key 列的条件,您现在应该使用 where('key', ...)。

factory 助手 ​

调用 factory(User::class, 1)->make() 或 factory(User::class, 1)->create() 现在将返回一个包含一个项目的集合。以前,这会返回一个单一模型。此方法仅在未提供数量时返回单一模型。

newPivot 方法 ​

Model::newPivot 方法签名已更新,添加了一个新的 $using 参数。新签名如下:

php
/**
 * 创建一个新的 pivot 模型实例。
 *
 * @param  \Illuminate\Database\Eloquent\Model  $parent
 * @param  array  $attributes
 * @param  string  $table
 * @param  bool  $exists
 * @param  string|null  $using
 * @return \Illuminate\Database\Eloquent\Relations\Pivot
 */
public function newPivot(Model $parent, array $attributes, $table, $exists, $using = null);

事件 ​

合同更改 ​

如果您在应用程序或包中手动实现 Illuminate\Contracts\Events\Dispatcher 接口,您应该将 fire 方法重命名为 dispatch。

事件优先级 ​

事件处理程序“优先级”支持已被移除。此未记录的功能通常表示滥用事件功能。相反,考虑使用一系列同步方法调用。或者,您可以在另一个事件的处理程序中调度新事件,以确保给定事件的处理程序在不相关的处理程序之后触发。

通配符事件处理程序签名 ​

通配符事件处理程序现在接收事件名称作为第一个参数,事件数据数组作为第二个参数。Event::firing 方法已被移除:

php
Event::listen('*', function ($eventName, array $data) {
    //
});

kernel.handled 事件 ​

kernel.handled 事件现在是一个基于对象的事件,使用 Illuminate\Foundation\Http\Events\RequestHandled 类。

locale.changed 事件 ​

locale.changed 事件现在是一个基于对象的事件,使用 Illuminate\Foundation\Events\LocaleUpdated 类。

illuminate.log 事件 ​

illuminate.log 事件现在是一个基于对象的事件,使用 Illuminate\Log\Events\MessageLogged 类。

异常 ​

Illuminate\Http\Exception\HttpResponseException 已重命名为 Illuminate\Http\Exceptions\HttpResponseException。请注意,Exceptions 现在是复数。同样,Illuminate\Http\Exception\PostTooLargeException 已重命名为 Illuminate\Http\Exceptions\PostTooLargeException。

邮件 ​

Class@method 语法 ​

不再支持使用 Class@method 语法发送邮件。例如:

php
Mail::send('view.name', $data, 'Class@send');

如果您以这种方式发送邮件,您应该将这些调用转换为 mailables。

新的配置选项 ​

为了支持 Laravel 5.4 的新 Markdown 邮件组件,您应该在 mail 配置文件的底部添加以下配置块:

php
'markdown' => [
    'theme' => 'default',

    'paths' => [
        resource_path('views/vendor/mail'),
    ],
],

使用闭包队列邮件 ​

为了队列邮件,您现在必须使用 mailable。使用 Mail::queue 和 Mail::later 方法队列邮件不再支持使用闭包配置邮件消息。此功能需要使用特殊库来序列化闭包,因为 PHP 本身不支持此功能。

队列 ​

失败的作业表 ​

如果您的应用程序包含 failed_jobs 表,您应该在表中添加一个 exception 列:

php
$table->longText('exception')->after('payload');

Redis ​

改进的集群支持 ​

Laravel 5.4 引入了改进的 Redis 集群支持。如果您正在使用 Redis 集群,您应该将集群连接放在 config/database.php 配置文件的 Redis 部分的 clusters 配置选项中:

php
'redis' => [

    'client' => 'predis',

    'options' => [
        'cluster' => 'redis',
    ],

    'clusters' => [
        'default' => [
            [
                'host' => env('REDIS_HOST', '127.0.0.1'),
                'password' => env('REDIS_PASSWORD', null),
                'port' => env('REDIS_PORT', 6379),
                'database' => 0,
            ],
        ],
    ],

],

路由 ​

Post 大小中间件 ​

类 Illuminate\Foundation\Http\Middleware\VerifyPostSize 已重命名为 Illuminate\Foundation\Http\Middleware\ValidatePostSize。

middleware 方法 ​

Illuminate\Routing\Router 类的 middleware 方法已重命名为 aliasMiddleware()。大多数应用程序可能从未手动调用此方法,因为它通常仅由 HTTP 内核调用以注册在 $routeMiddleware 数组中定义的路由级中间件。

Route 方法 ​

Illuminate\Routing\Route 类的 getUri 方法已被移除。您应该使用 uri 方法。

Illuminate\Routing\Route 类的 getMethods 方法已被移除。您应该使用 methods 方法。

Illuminate\Routing\Route 类的 getParameter 方法已被移除。您应该使用 parameter 方法。

Illuminate\Routing\Route 类的 getPath 方法已被移除。您应该使用 uri 方法。

会话 ​

Symfony 兼容性 ​

Laravel 的会话处理程序不再实现 Symfony 的 SessionInterface。实现此接口要求我们实现框架不需要的多余功能。相反,定义了一个新的 Illuminate\Contracts\Session\Session 接口,可以使用。还应应用以下代码更改:

所有对 ->set() 方法的调用应更改为 ->put()。通常,Laravel 应用程序不会调用 set 方法,因为它从未在 Laravel 文档中记录。然而,这里出于谨慎考虑而包含。

所有对 ->getToken() 方法的调用应更改为 ->token()。

所有对 $request->setSession() 方法的调用应更改为 setLaravelSession()。

测试 ​

Laravel 5.4 的测试层已被重写,以便开箱即用地更简单和更轻。如果您希望继续使用 Laravel 5.3 中的测试层,您可以将 laravel/browser-kit-testing 包 安装到您的应用程序中。此包提供与 Laravel 5.3 测试层的完全兼容性。实际上,您可以在同一应用程序中同时运行 Laravel 5.4 测试层和 Laravel 5.3 测试层。

为了允许 Laravel 自动加载您使用 Laravel 5.4 测试生成器生成的任何新测试,您应该将 Tests 命名空间添加到 composer.json 文件的 autoload-dev 块中:

php
"psr-4": {
    "Tests\\": "tests/"
}

在单个应用程序中运行 Laravel 5.3 和 5.4 测试 ​

首先安装 laravel/browser-kit-testing 包:

php
composer require --dev laravel/browser-kit-testing "1.*"

安装包后,创建 tests/TestCase.php 文件的副本,并将其保存到 tests 目录中为 BrowserKitTestCase.php。然后,修改文件以扩展 Laravel\BrowserKitTesting\TestCase 类。完成此操作后,您应该在 tests 目录中有两个基本测试类:TestCase.php 和 BrowserKitTestCase.php。为了正确加载 BrowserKitTestCase 类,您可能需要将其添加到 composer.json 文件中:

php
"autoload-dev": {
    "psr-4": {
        "Tests\\": "tests/"
   }
}

在 Laravel 5.3 上编写的测试将扩展 BrowserKitTestCase 类,而使用 Laravel 5.4 测试层的任何新测试将扩展 TestCase 类。您的 BrowserKitTestCase 类应如下所示:

php
<?php

use Illuminate\Contracts\Console\Kernel;
use Laravel\BrowserKitTesting\TestCase as BaseTestCase;

abstract class BrowserKitTestCase extends BaseTestCase
{
    /**
     * 应用程序的基本 URL。
     *
     * @var string
     */
    public $baseUrl = 'http://localhost';

    /**
     * 创建应用程序。
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Kernel::class)->bootstrap();

        return $app;
    }
}

创建此类后,请确保更新所有测试以扩展新的 BrowserKitTestCase 类。这将允许您在 Laravel 5.3 上编写的所有测试继续在 Laravel 5.4 上运行。如果您愿意,您可以慢慢开始将它们移植到新的 Laravel 5.4 测试语法 或 Laravel Dusk。

注意

如果您正在编写新测试并希望它们使用 Laravel 5.4 测试层,请确保扩展 TestCase 类。

在升级的应用程序中安装 Dusk ​

如果您希望在从 Laravel 5.3 升级的应用程序中安装 Laravel Dusk,首先通过 Composer 安装它:

php
composer require --dev laravel/dusk "1.*"

接下来,您需要在 tests 目录中创建一个 CreatesApplication trait。此 trait 负责为测试用例创建新的应用程序实例。trait 应如下所示:

php
<?php

use Illuminate\Contracts\Console\Kernel;

trait CreatesApplication
{
    /**
     * 创建应用程序。
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Kernel::class)->bootstrap();

        return $app;
    }
}

注意

如果您已为测试命名空间并使用 PSR-4 自动加载标准加载 tests 目录,您应该将 CreatesApplication trait 放在适当的命名空间下。

完成这些准备步骤后,您可以按照正常的 Dusk 安装说明 进行操作。

环境 ​

Laravel 5.4 测试类不再手动为每个测试强制 putenv('APP_ENV=testing')。相反,框架利用从加载的 .env 文件中的 APP_ENV 变量。

事件伪造 ​

Event 伪造的 assertFired 方法应更新为 assertDispatched,assertNotFired 方法应更新为 assertNotDispatched。方法的签名没有更改。

邮件伪造 ​

Mail 伪造在 Laravel 5.4 版本中大大简化。您不再使用 assertSentTo 方法,而是简单地使用 assertSent 方法,并在回调中使用 hasTo、hasCc 等辅助方法:

php
Mail::assertSent(MailableName::class, function ($mailable) {
    return $mailable->hasTo('email@example.com');
});

翻译 ​

{Inf} 占位符 ​

如果您正在使用 {Inf} 占位符来复数化您的翻译字符串,您应该更新您的翻译字符串以使用 * 字符:

php
{0} First Message|{1,*} Second Message

trans 助手 ​

trans 助手签名已更新,删除了不必要的 $domain 参数。新签名如下:

php
/**
 * 翻译给定的消息。
 *
 * @param  string  $id
 * @param  array   $replace
 * @param  string  $locale
 * @return \Illuminate\Contracts\Translation\Translator|string|array|null
 */
function trans($id = null, $replace = [], $locale = null);

此外,trans_choice 助手已更新:

php
/**
 * 根据计数翻译给定的消息。
 *
 * @param  string  $id
 * @param  int|array|\Countable  $number
 * @param  array   $replace
 * @param  string  $locale
 * @return string
 */
function trans_choice($id, $number, array $replace = [], $locale = null);

URL 生成 ​

forceSchema 方法 ​

Illuminate\Routing\UrlGenerator 类的 forceSchema 方法已重命名为 forceScheme。

验证 ​

日期格式验证 ​

日期格式验证现在更加严格,并支持 PHP date 函数 文档中存在的占位符。在以前的 Laravel 版本中,时区占位符 P 会接受所有时区格式;然而,在 Laravel 5.4 中,每个时区格式都有一个独特的占位符,如 PHP 文档所示。

方法名称 ​

addError 方法已重命名为 addFailure。此外,doReplacements 方法已重命名为 makeReplacements。通常,这些更改仅在您扩展 Validator 类时相关。

杂项 ​

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