从 5.2.0 升级到 5.3.0
预计升级时间:2 – 3 小时
PHP & HHVM
Laravel 5.3 需要 PHP 5.6.4 或更高的版本,HHVM 将不再做官方支持,因为它与 PHP 5.6+ 并不是包含完全相同的特性。
数组
Key / Value 顺序做了更改
Arr
类的 first
, last
, contains
方法回调函数的第一个参数现在需要传 ‘value
’。例如:
Arr::first(function ($value, $key) { return ! is_null($value); });
在 Laravel 上一个版本中,$key
是第一个传递的。由于大多数使用情况中只会关心 $value
,所以现在它作为第一个参数。你需要在应用中对这三个方法做一个全局搜索,以核对 $value
是否是作为回调函数的第一个参数传递的。
Artisan
make:console
命令
make:console
重命名为了 make:command
用户认证
Authentication 脚手架
框架中默认提供的两个用户认证控制器分成了四个小的控制器。这个变更提供了更加简洁、清晰的用户认证控制器。把你的应用升级到新的用户认证的最简单的方式是从 Github 上获取最新的拷贝并放置到你的应用中。
你还需要确保在应用中的 routes.php
文件中调用 Route::auth()
方法,这个方法会为新的用户认证注册合适的路由。
当这些控制器放到你的应用中后,你需要重新实现你对这些控制器做的修改。例如,你修改过用户认证的 guard
,那你可能需要重写控制器的 guard
方法,你可以检查每一个用户认证控制器的 trait 来决定覆盖哪些方法。
routes.php
文件中是否有调用 Route::auth
方法。密码重置邮件
密码重置邮件现在使用新的 Laravel 通知功能。当发送密码重置链接的时候,如果你想定制发送的通知,你可以覆盖 Illuminate\Auth\Passwords\CanResetPassword
trait 的 sendPasswordResetNotification
方法。
你的 User
模型必须 use
新的 Illuminate\Notifications\Notifiable
trait 以确保密码重置链接邮件可以成功发送。
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; }
config/app.php
配置文件的 providers
数组中注册 Illuminate\Notifications\NotificationServiceProvider
。Logout 使用 POST 方法
Route::auth
方法会为 /logout
注册一个 POST
路由而非 GET
路由。这可以组织其他 WEB 应用能够登出你的应用的用户。升级的话,你或者更改你的登出请求使用 POST
方法,或者为 /logout
URI 注册一个你自己的 GET
路由。
Route::get('/logout', 'Auth\LoginController@logout');
用户授权
使用 Class 名称调用 Policy 方法
一些 policy 方法只接受当前认证的用户,而非他们授权的模型的实例。最常见的是认证 create
方法。例如,当你发布一篇博客的时候,你可能希望检查这个用户是否具有发布博客的权限。
当定义不接受模型实例的 policy 方法的时候,例如 create
方法,类名将不再通过方法的第二个参数传递。你的方法只需要传递一个认证的用户实例。
/** * Determine if the given user can create posts. * * @param \App\User $user * @return bool */ public function create(User $user) { // }
AuthorizesResources
trait
AuthorizesResources
trait 现在已经与 AuthorizesRequests
trait 合并,你需要删除 app/Http/Controllers/Controller.php
文件中的 AuthorizesResources
trait。
Blade 模板
自定义指令
在 Laravel 上一个版本中,使用 directive
方法自定义 Blade 指令的时候,传递给回调函数的 $expression
必须包含在一个大括号内。
在 Laravel 5.3 中,包围在传递给回调函数的 $expression
外的大括号已经取消了。请查看 Blade 扩展 文档,并检查你定义的 Blade 指令是否还能正常使用。
// Laravel 5.2 Blade::directive('datetime', function($expression) { return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>"; }); // Laravel 5.3 Blade::directive('datetime', function($expression) { return "<?php echo $expression->format('m/d/Y H:i'); ?>"; });
缓存
扩展闭包绑定了 $this
当使用闭包调用 Cache::extend
方法的时候,$this
会绑定到 CacheManager
实例,允许你在闭包中调用它的方法:
Cache::extend('memcached', function ($app, $config) { try { return $this->createMemcachedDriver($config); } catch (Exception $e) { return $this->createNullDriver($config); } });
集合
Key / Value 顺序变更
first
, last
, contains
集合方法使用 value
作为回调函数的第一个参数,例如:
$collection->first(function ($value, $key) { return ! is_null($value); });
在上一个版本的 Laravel 中,$key
是第一个参数。由于大多数使用情况中只关注 $value
,它现在作为第一个参数传递。你需要在应用中对这三个方法做一个全局查找,检查 $value
是否是作为第一个参数传递的。
where
比较现在默认为宽松的
where
方法现在默认提供了一种宽松的比较而非严格比较,如果你要做一个严格比较的话,你可以使用 whereStrict
方法。
where
方法现在已经不再接受第三个参数来指定是否是“严格的”。你需要根据应用的需要明确指定调用 where
或 whereStrict
方法。
数据库
集合
Query Builder 现在返回一个 Illuminate\Support\Collection
实例而非数组。这确保了 Query Builder 与 Eloquent 返回结果的一致性。
如果你不想把 Query Builder 查询结果合并为 Collection
实例,你可以在 Query Builder 的 get
方法后连接一个 all
方法。这将返回一个纯 PHP 的数组,允许你向后兼容维护。
$users = DB::table('users')->get()->all();
Eloquent $morphClass
属性
Eloquent 模型中可以定义的 $morphClass
属性已经被移除,被 “morph map” 取代。定义 morph map
可以为预加载提供支持,并解决了多态关系中额外的 BUG。如果你之前依赖 $morphClass
属性的话,可以使用下面的语法迁移到 morphMap
:
Relation::morphMap([ 'YourCustomMorphName' => YourModel::class, ]);
例如,你之前定义了下面的 $morphClass
属性:
class User extends Model { protected $morphClass = 'user' }
你需要在 AppServiceProvider
的 boot
方法中定义下面的 morphMap
:
use Illuminate\Database\Eloquent\Relation; Relation::morphMap([ 'user' => User::class, ]);
Eloquent 的 save
方法
现在,当模型没有更改的话,save
方法将返回 false
。
Eloquent scopes
Eloquent scopes
现在优先考虑布尔值的 scope
约束。例如,当你的 scope
以 orWhere
约束开始的话,它将不再转换为 where
。如果你依赖这个功能(例如,在一个循环中添加多个 orWhere
条件),你需要核实第一个条件是普通的 where
以避免任何布尔逻辑问题。
如果你的 scope
以 where
开始,则不需要进行任何修改。记得,你可以通过 toSql
方法来查看查询语句:
User::where('foo', 'bar')->toSql();
Join
闭包
JoinClause
类已经重写,以统一与 Query Builder 的语法。on
闭包函数中可选的 $where
参数已经取消。要添加 where
条件的话,你可以使用 Query Builder 提供的 where
方法:
$query->join('table', function($join) { $join->on('foo', 'bar')->where('bar', 'baz'); });
$bindings
属性也被移除了。想要使用 join
绑定的话,你可以直接使用 addBinding
方法:
$query->join(DB::raw('('.$subquery->toSql().') table'), function($join) use ($subquery) { $join->addBinding($subquery->getBindings(), 'join'); });
加密
Mcrypt encrypter 已经移除
2015 年 6 月发布 Laravel 5.1.0 的时候就已经弃用,在 5.3.0 中已经完全移除了,取而代之的是基于 OpenSSL 的新的算法实现,它自 Laravel 5.1.0 之后就一直作为默认的算法。
如果在 config/app.php
文件中你还在使用基于 cipher
的算法,你需要把它更改为 AES-256-CBC
,并把 key
设置为 32 位的随机字符串,可以通过 php artisan key:generate
来生成。
如果你已经在数据库中存储着 Mcrypt encrypter 的加密结果,你可以安装 laravel/legacy-encrypter
包,它包含了遗留的 Mcrypt encrypter 实现。你应该使用这个包解密加密过的数据,并重新使用新的 OpenSSL 算法加密。例如你可以在自定义 Artisan 命令中像下面这样做:
$legacy = new McryptEncrypter($encryptionKey); foreach ($records as $record) { $record->encrypted = encrypt( $legacy->decrypt($record->encrypted) ); $record->save(); }
异常处理
构造函数
默认的异常处理现在需要给构造函数传递一个 Illuminate\Container\Container
实例。这个更改只会在你的应用的 app/Exception/Handler.php
文件中定义了 __construct
方法的时候受影响。如果你这么做了,你需要给 parent::__construct
方法传递一个 container
实例:
parent::__construct(app());
中间件
can
中间件的命名空间修改
在 HTTP kernel 中列出的 $routeMiddleware
属性中的 can
中间件需要更改为下面的类:
'can' => \Illuminate\Auth\Middleware\Authorize::class,
can
中间件认证异常
现在当用户未认证的时候,can
中间件会抛出一个 Illuminate\Auth\AuthenticationException
实例。你需要更改程序捕获该异常。多数情况下,这个更改不会影响你的应用程序。
绑定 Substitution
中间件
路由模型绑定现在支持使用中间件。所有应用现在都需要给 app/Http/Kernel.php
文件中的 web
中间件组添加 Illuminate\Routing\Middleware\SubstituteBindings
中间件。
\Illuminate\Routing\Middleware\SubstituteBindings::class,
并且需要在 HTTP kernel 的 $routeMiddleware
属性中注册该路由中间件:
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
路由中间件注册后,你需要把它添加到 api
中间件组中:
'api' => [ 'throttle:60,1', 'bindings', ],
通知
安装
Laravel 5.3 提供了一个新的、基于驱动的通知系统。你需要在 config/app.php
文件的 providers
数组中注册 Illuminate\Notifications\NotificationServiceProvider
。并且需要在 alias 数组中添加 Illuminate\Support\Facades\Notification
Facade。最后你可以在 User
模型或其他需要接收通知的模型中使用 Illuminate\Notifications\Notifiable
trait。
分页
自定义
Laravel 5.3 与之前的 Laravel 5.x 版本相比,自定义分页生成的 HTML 更加容易了。你只需定义一个 Blade 模板即可,而不在需要定义 Presenter
类了。最简单的方法是通过 vendor:publish
命令把它们导出到 resources/views/vendor
目录:
php artisan vendor:publish --tag=laravel-pagination
这个命令会把视图放到 resources/views/vendor/pagination
文件夹中。文件夹中的 default.blade.php
对应的是默认的分页视图。只需编辑这个文件更改生成的分页 HTML。
请查看 分页 文档来获取更多内容。
队列
配置
在队列配置文件中,所有的 expire
配置项都要重命名为 retry_after
。同样的,Beanstalk 配置的 ttr
也需要重命名为 retry_after
。这个更改为配置项提供了更加清晰的目的。
闭包
队列闭包现在已经不再支持。如果你的应用使用闭包处理队列,你需要把闭包转换为一个类,并处理这个类的实例。
集合序列化
Illuminate\Queue\SerializesModels
trait 现在可以正确的序列化 Illuminate\Database\Eloquent\Collection
的实例。对于大多数应用来说,这并不是一个破坏性的更改。但是如果你的应用依赖于不是通过 queued job 获取的数据集的 collections
,那你应该核对下这个更改是否影响你的应用。
后台驻留任务
当调用 queue:work
命令时,不再需要指定 --daemon
选项了。运行 php artisan queue:work
命令会自动假定你想要在后台驻留程序中运行该任务。如果你想处理单一的任务,你需要使用该命令的 --once
选项:
// Start a daemon queue worker... php artisan queue:work // Process a single job... php artisan queue:work --once
事件数据更改
各种队列任务事件如 JobProcessing
和 JobProcessed
不再包含 $data
属性。你需要更新应用调用 $event->job->payload()
方法来获取相应的数据。
失败任务表
你的应用有个 failed_jobs
表,你需要为表添加一个 exception
列,exception
应该是 TEXT
类型的,用于存储导致任务失败的相应的字符串。
在遗留的队列任务中序列化模型
一般情况下,Laravel 的任务是通过给 Queue::push
传递一个任务实例实现队列化,然而,有些应用可能使用下面遗留的语法来序列化任务:
Queue::push('ClassName@method');
如果你使用这个语法来序列化任务,Eloquent 模型将不再自动序列化,并在队列中重新取回。如果你希望 Eloquent 模型在队列中自动序列化,你需要在任务类中使用 Illuminate\Queue\SerializesModels
trait,并使用新的 push
语法队列化任务:
Queue::push(new ClassName);
路由
resource
参数将默认为单数
在上一个 Laravel 版本中,使用 Route::resource
注册的路由是非单数的。这在路由模型绑定中可能会导致一些意想不到的行为。例如,给定下面的 Route::resource
调用:
Route::resource('photos', 'PhotoController');
show
的 URI 将定义为下面这样:
/photos/{photos}
在 Laravel 5.3 中,所有的参数都将默认为单数。因此,相同的 Route::resource
调用将注册下面的 URI:
/photos/{photo}
如果你想维持之前的行为,而非把 resource
路由参数转为单数,你可以在 AppServiceProvider
中调用 singularResourceParameters
方法:
use Illuminate\Support\Facades\Route; Route::singularResourceParameters(false);
resource
路由名称将不再受前缀影响
当使用 Route::resource
时,URL 前缀将不再影响分配的路由名称,因为这个行为会导致希望使用路由名称为第一位的目的失败。
如果你的应用在指定了 prefix
的 Route::group
中调用 Route::resource
,你需要检查所有调用 route
辅助方法的地方,确保已经不再在路由名称前添加 prefix
URI。
如果这个更改导致你有两个路由使用相同的名称,当调用 Route::resource
的时候你可以使用 names
选项来给一个指定的路由定义名称。参考 resource 路由 获取更多内容。
验证
Form Request 异常
如果表的请求验证失败,Laravel 现在回抛出一个 Illuminate\Validation\ValidationException
实例而非 HttpException
实例。如果你手动捕获有表单请求抛出的 HttpException
实例,你需要更新 catch
代码块来捕获 ValidationException
异常。
原始的 Nullable
当验证数组、布尔、整型、数字、以及字符串的时候, null
将不再作为一个正确的值,除非指定了新的 nullable
规则:
Validate::make($request->all(), [ 'string' => 'nullable|max:5', ]);
该篇属于专题:《Laravel 5.3 中文文档》
- 下一篇: 《「Laravel 5.3 中文文档」开始 – 安装》
php 2016/08/21 17:44
赞,laravel又升级了,要求php5.6+,可惜现在还在用5.0.。。。
Specs 2016/08/21 19:15
@ 都这个年代了,还用 5.0 啊。。人家很多都在用 7.0 了~