6.0升级到6.1版本由于安全性原因,6.1版本移除核心对think-filesystem库的依赖,因此6.0版本升级至6.1版本后,需要单独安装topthink/think-filesystem库。
5.1升级到6.0版本不建议老的项目升级到新版,除非你有重构计划,否则就算升级了也只是表面上升级了。
本文主要用于指导开发者从
5.1升级到6.0最新版本,由于6.0不支持5.1的无缝升级,下面的升级步骤和指导仅供学习参考,或有遗漏及考虑不周之处,因此不保证你的所有功能都能正常升级。
6.0版本必须使用composer安装,所以你需要首先安装新的6.0版本,然后把原来5.1的文件复制进去,完成升级工作。
composer create-project topthink/think:6.0.0 tp安装完成后,把原来application目录下面的文件复制到app目录下面,然后把config和route目录下的文件复制到同名目录下。接下来,按照下面的步骤来升级操作。
从5.1多模块迁移到6.0的多应用后,应用类库的命名空间原则上可以无需调整,但不再支持跨应用调用(包括路由及模板,每个应用的路由是独立的),这点务必引起重视。如果你的应用根命名空间不是默认的app需要改成app。
如果原来你使用了多模块开发模式,直接改成新版的多应用模式是最简单的,需要额外安装多应用模式扩展。
composer require topthink/think-multi-app如果你自定义了访问控制器的名称,需要修改route.php配置文件中的controller_layer值。
// 访问控制器层名称'controller_layer'      => 'controller',如果你开启了控制器类的后缀,需要设置route.php配置文件中的controller_suffix值。
// 开启控制器后缀'controller_suffix'     => true,如果自定义了空控制器的名称,则需要设置route.php配置文件中的empty_controller值。
// 空控制器名'empty_controller'      => 'Error',请按照如下顺序检查及调整你的配置文件和相关配置代码。
如果是多应用的话,应用配置文件应当放入应用下的config目录。全局配置文件位置无需调整。
原来获取一级配置参数的方式
Config::pull('app');需要改成
Config::get('app');所有的配置读取必须从第一级配置开始,例如,原来的
Config::get('exception_handle');必须改成
Config::get('app.exception_handle');动态更改配置参数的用法已经废弃,下面的用法不再支持。
Config::set('route.default_return_type', 'json');如果你需要把数据库的配置参数读入配置,可以使用
$config = Db::name('config')->column('value', 'name');Config::set($config, 'route');Config类不再支持数组方式读取Config类不再使用ArrayAccess接口,因此不再支持数组方式读取。
路由和URL请求相关的配置参数独立为route.php配置文件,而不再使用app.php配置文件。
单应用模式下,路由定义文件和之前一样就在route目录下面,如果你的项目是采用了多应用模式的话,每个应用的路由定义和匹配都是独立的,也没有模块的概念,路由定义文件的位置应该是在应用/route下面,例如:
app/index/route/route.php //  index应用的路由定义文件app/index/route/web.php //  index应用的第二个路由定义文件app/admin/route/route.php // admin应用的路由定义文件应用的路由规则其实是定义的入口文件(或者应用名)后面的URL部分,而不包含应用。
首先如果你的路由定义采用的是返回数组形式,全部改成方法定义。
例如:
return [    'hello/:name' => 'index/hello',];必须改成:
Route::get('hello/:name', 'index/hello');如果路由定义方法(包括rule/get/post/put/delete/patch/miss/group等方法)使用了option和pattern参数,全部改成方法调用形式,例如原来的:
Route::get('hello/:name', 'index/hello', [ 'ext'  =>  'html'], [ 'name'  => '\w+']);需要改成
Route::get('hello/:name', 'index/hello')    ->ext('html')    ->pattern([ 'name'  => '\w+']);如果路由分组定义使用了数组,改成闭包方式定义,例如:
Route::group('blog', [    ':id'   => 'Blog/read',    ':name' => 'Blog/read',])->ext('html')->pattern(['id' => '\d+']);必须改成
Route::group('blog', function() {    Route::get(':id', 'Blog/read');    Route::get(':name', 'Blog/read');})->ext('html')->pattern(['id' => '\d+']);如果你需要注册一个虚拟的路由分组,可以直接在第一个参数使用闭包
Route::group(function() {    Route::get('blog/:id', 'Blog/read');    Route::get('user/:name', 'User/read');})->ext('html')->pattern(['id' => '\d+']);url_controller_layer配置改为在route.php配置文件中使用controller_layer设置。
controller_suffix配置改为在route.php配置文件中使用controller_suffix设置。
同时class_suffix配置参数已经无效。
mergeExtraVars方法和对应参数改为在路由规则中明确指定变量规则。
allowCrossDomain方法参数调整取消原来的第一个参数。
header方法取消需要单独改变Header信息的直接通过中间件统一处理。
Request类的hook方法该方法已经在最新版本中取消。如果你使用了该功能,在自定义请求对象app\Request中直接增加相应的方法即可。并确保provider.php文件中添加如下绑定:
'think\Request' => \app\Request::class,URL参数模式配置原来的URL参数模式配置参数url_param_type,统一使用参数/值的方式。如果你设置了该配置参数为1,必须改成定义路由的方式。
因为使用场景有限和性能开销问题,取消原来的别名路由功能,建议使用资源路由或者单独的路由替代。
因为使用场景有限和不太符合规范,取消了原来的控制器快捷路由功能。
建议使用分组MISS路由功能或者控制器的__call方法替代。
think\Controller类取消系统不再提供基础控制器类think\Controller,原来的success、error、redirect和result方法需要自己在基础控制器类里面实现。
系统默认在应用目录下面提供了一个app\BaseController基础类,或者你可以直接放入你的应用里面,继承使用。
你可以安装下面的扩展用于支持旧版本的跳转操作
composer require liliuwei/thinkphp-jump模板引擎类不再内置到核心框架,但使用
composer create-project topthink/think会默认安装该组件(如果不需要使用的话可以自己卸载topthink/think-view)。
安装后,由于内置的think\Controller类已经取消,如果你的控制器类需要调用fetch/display/assign等视图方法,必须改为调用think\facade\View类,如果是使用view助手函数方式的话,可以无需调整。
View::assign('name', $name);View::fetch();share方法取消原来视图类的share方法取消,可以使用
think\facade\View::assign($vars);Db改为使用门面对象新版的Db类不再是静态类,需要使用think\facade\Db门面进行静态代理。
\think\facade\Db::name('user')->find();数据库配置文件或者connect方法取消DSN数据库配置定义方式,全部采用数组方式配置定义。
Db::connect('mysql://root:1234@127.0.0.1:3306/thinkphp#utf8')	->table('user')    ->find();必须改成
Db::connect('db_config')	->table('user')    ->find();并且按照新版的规范在数据库配置文件中增加db_config连接信息。
fetchPdo方法取消了Query类的fetchPdo方法,需要的时候直接使用getPdo方法替代。
Query对象取消Query类的CURD查询方法传入当前对象,如果需要请使用闭包替代。
insert/insertGetId/insertAll方法取消replace参数insert/insertGetId/insertAll方法的第二个replace参数已经取消,改为使用replace方法。
$data = ['foo' => 'bar', 'bar' => 'foo'];Db::name('user')->insert($data, true);需要改为
$data = ['foo' => 'bar', 'bar' => 'foo'];Db::name('user')->replace()->insert($data);db和model助手函数这两个助手函数5.1版本已经不再建议使用了,6.0版本已经废弃掉这两个助手函数,请直接使用\think\facade\Db类静态方法和实际的模型类调用。
setInc/setDec方法取消Query类的setInc/setDec方法,统一使用inc/dec方法替代。例如:
Db::name('user')->where('id', 1)    ->inc('exp')    ->dec('score')    ->update();join方法的批量操作join方法不再支持批量操作多个表,如果你使用了join方法批量操作,需要改成每个表单独调用一次join方法。
setField方法取消Query类的setField方法,请直接使用data方法或者update方法。
__TABLE_NAME__支持table方法取消__TABLE_NAME__支持,必须明确调用完整表名或者使用name方法。
whereOr等方法传入Query对象因为Query对象查询只能使用一次,除了where方法本身可以传入Query对象外,其它的所有where查询方法(例如whereOr/whereExp等)都不再支持传入Query对象。
resultset_type配置参数数据集查询结果不再受resultset_type配置参数影响,默认情况下,Db查询统一返回数组,模型查询统一返回模型对象和模型数据集对象。如果Db查询的时候也需要返回数据集的话,可以显式调用fetchCollection方法。
Query类的extend方法取消了Query类的extend方法,如果需要扩展查询方法,建议自定义Query类并继承系统的think\db\Query类即可,然后在模型中定义query属性或者配置数据库连接的query参数为你的自定义类。
Expression对象调整原来的Expression对象已经更改为更适合的Raw对象,但不影响Db::raw()方法的调用。
eq/neq/gt/lt/egt/elt表达式由于存在两种用法,并且不够直观,全部统一为更直观的用法。
下面的用法不再支持
Db::name('user')->where('id', 'egt', 1)    ->where('status', 'neq' ,1)    ->select();统一使用
Db::name('user')->where('id', '>=', 1)    ->where('status', '<>' ,1)    ->select();出于分表的性能问题和复杂性,不再提供分表方法,建议使用数据库的分区功能替代。新版可以使用partition方法指定当前查询的分区。
数据库的查询次数合并到queryTimes,不再区分读写操作,你可以使用下面的方法获取当前请求的数据库查询次数(包括读写)
Db::getQueryTimes();如果之前开启了类库后缀功能的话,你必须在模型类里面明确指定name属性。
get/all方法无论使用Db类还是模型类查询,全部统一使用find/select方法,取消了之前模型类额外提供的get/all方法。同时取消的方法还包括getOrFail/allOrFail。
base方法取消模型类的全局查询范围base方法,改由使用globalScope属性定义(数组)需要全局查询的查询范围方法。
模型事件不再需要使用event方法注册事件,统一在模型类中定义事件方法,例如
<?phpnamespace app\index\model;use think\Model;class User extends Model{    public function onAfterRead($user)    {        $user->extra = 'extra';    }    public function onBeforeWrite($user)    {        $user->extra = 'extra';    }}并且模型增加after_read事件,在查询后创建模型对象实例的时候触发。
模型的自动完成功能已经取消,请使用模型事件代替。
save方法调整模型类的save方法不再支持where参数。
如果你的关联统计使用了闭包方式返回关联统计字段,需要调整为如下方式:
User::withCount(['cards' => function($query,&$name) {    $query->where('status', 1);    $name = 'card_count';}])->select();取消hidden/visible/append方法的第二个参数,当你调用这几个方法的时候,无论模型是否设置了相关属性,都会直接覆盖之前设置的值。
如果希望在更新和删除之后自动清除之前的查询缓存,必须在cache方法中传入key值而不是true。
selfRelation方法如果你在定义关联的时候使用了selfRelation方法,请直接删除该方法,目前已经不再需要,会自动识别是否为自关联。
setEagerlyType方法一对一关联无需在定义关联的时候指定为JOIN查询,在查询的时候直接使用withJoin方法即可使用JOIN方式进行关联查询。
多对多关联的pivotDataName方法更名为更简单的name方法。
行为和Hook已经用新版的事件机制替代,需要把你的行为改成事件响应或者中间件(部分请求拦截的行为可以直接改为中间件)。
原来的系统内置钩子的行为类
<?phpnamespace app\index\behavior;class Hello{    public function run($params)    {        // 行为逻辑    }}可以改成事件监听类
namespace app\index\listener;class Hello{    public function handle($event)    {        // 事件监听处理    }}然后在应用目录的event.php文件中配置事件监听。
return [    'listen'    =>    [        'AppInit'    =>    ['\app\index\listener\Hello'],        // 更多事件监听    ],];修改完成后,你可以删除应用目录下不再使用的tags.php文件。
内置事件和钩子的对应关系如下:
| 事件 | 对应 5.1钩子 | 参数 | 
|---|---|---|
| AppInit | app_init | 无 | 
| AppEnd | app_end | 当前响应对象实例 | 
| LogWrite | log_write | 当前写入的日志信息 | 
| LogLevel | log_level | 包含日志类型和日志信息的数组 | 
原来的
app_begin、response_send、response_end、action_begin、module_init和view_filter钩子已经废弃。
Facade类库别名取消系统Facade类库的别名已经取消,因此不能再使用
use Route;Route::rule('hello/:name', 'index/hello');必须使用
use think\facade\Route;Route::rule('hello/:name', 'index/hello');Session调整Session新版默认不开启,必须为在全局中间件定义文件中添加
'think\middleware\SessionInit'原来的Session::get() 可以获取全部的Session数据必须改成 Session::all()
由于新版框架核心类库全面启用强类型参数,并且使用严格模式,所以在调用系统方法的时候一定要注意参数的类型,或者注意看抛出的异常信息进行修正。
最后,希望你的
6.0升级之旅顺利^_^ ,希望大家在升级和使用6.0的过程中,多反馈和建议,帮助我们尽快完善和发布正式版本。