# 升级指导
# 5.1版本升级指导
本章节的内容告诉你进行`5.1.*`版本的升级须知和建议,由于一些必要原因,个别版本的升级并非完全无缝,请尽量按照本升级指导的建议进行调整。
- [从`5.1.14`升级到`5.1.15`](#51145115_6)
- [从`5.1.13`升级到`5.1.14`](#51135114_10)
- [从`5.1.12`升级到`5.1.13`](#51125113_23)
- [从`5.1.11`升级到`5.1.12`](#51115112_27)
- [从`5.1.10`升级到`5.1.11`](#51105111_31)
- [从`5.1.9`升级到`5.1.10`](#5195110_35)
- [从`5.1.8`升级到`5.1.9`](#518519_51)
- [从`5.1.7`升级到`5.1.8`](#517518_95)
- [从`5.1.6`升级到`5.1.7`](#516517_101)
- [从`5.1.5`升级到`5.1.6`](#515516_105)
- [从`5.1.0`升级到`5.1.5`](#510515_155)
- [从`5.0`升级到`5.1`](#5051_159)
## 从`5.1.14`升级到`5.1.15`
从`5.1.14`版本可以无缝升级到`5.1.15`。
## 从`5.1.13`升级到`5.1.14`
从`5.1.13`版本基本可以无缝升级到`5.1.14`。
> 补充一点,如果动态配置设置`view_path`(在新版中不要动态配置,因为容器中的对象一旦实例化后是不会每次读取动态配置值的,减少依赖,也更方便单元测试),需要改成在控制器中调用:
>
>
> ```
> $this->view->config('view_path','path');
>
> ```
> 或者使用了view方法输出的话,可以使用
>
>
> ```
> think\facade\View::config('view_path','path');
>
> ```
## 从`5.1.12`升级到`5.1.13`
从`5.1.12`版本可以无缝升级到`5.1.13`。
## 从`5.1.11`升级到`5.1.12`
从`5.1.11`版本可以无缝升级到`5.1.12`。
## 从`5.1.10`升级到`5.1.11`
从`5.1.10`版本可以无缝升级到`5.1.11`。
## 从`5.1.9`升级到`5.1.10`
如果数组查询条件中使用了`exists`查询,必须做出如下调整:
```
// 错误
$where[] = ['', 'exists', 'select * from user where status = 0'];
// 正确
$where[] = ['', 'exists', Db::raw('select * from user where status = 0')];
```
建议的方式是使用
```
$model->whereExists('select * from user where status = 0')->select();
```
## 从`5.1.8`升级到`5.1.9`
从`5.1.8`升级到`5.1.9`的时候,请注意如下事项:
下面方式的数组条件查询不再使用索引数组
```
// 错误
$where['name'] = ['name', 'like', 'think'];
// 正确
$where[] = ['name', 'like', 'think'];
```
但对于基本条件查询不受影响
```
// 正确
$where['name'] = 'think';
```
但并不支持混合查询:
```
// 错误
$where['name'] = 'think';
$where[] = ['id', '<=', 10];
```
如果数组查询条件中使用了`exp`查询,必须做出如下调整:
```
// 错误
$where[] = ['id', 'exp', '>score'];
// 正确
$where[] = ['id', 'exp', Db::raw('>score')];
```
表达式查询方式不受影响。
> 如果你使用了闭包查询条件,并且使用了默认的查询缓存`cache()`或者`cache(true)`,新版本会抛出异常,请使用`cache('key')`替代,避免因为查询缓存无效而影响业务。
另外可能不影响但推荐使用的建议:
> `order/field/where`方法如果使用字符串参数并涉及到SQL函数的,推荐使用`orderRaw/fieldRaw/whereRaw`方法,或者对传入的字符串参数使用`Db::raw()`方法。
## 从`5.1.7`升级到`5.1.8`
从`5.1.7`版本可以无缝升级到`5.1.8`。
如果你从`5.1.5`直接升级的话,可以通过配置 `template.auto_rule` 参数为2,兼容之前的默认模板渲染规则。
## 从`5.1.6`升级到`5.1.7`
从`5.1.6`版本可以无缝升级到`5.1.7`。
## 从`5.1.5`升级到`5.1.6`
> 从`5.1.5`升级到`5.1.6`的过程需要注意如下事项:
### 路由变量规则调整
路由变量规则的定义不再支持使用模式修饰符和诸如`^\d+$`这种限定符。
例如
```
Route::rule('hello/:name','hello')
->pattern('name','/^\w{4}+$/i');
```
需要调整为
```
Route::rule('hello/:name','hello')
->pattern('name','\w{4}+');
```
### 路由标识用法调整
原来的
```
Route::name('路由标识')->rule('rule','route');
```
需要改成
```
Route::rule('rule','route')->name('路由标识');
```
### EXP表达式更新
出于安全性考虑,如果使用了`EXP`表达式更新,请使用`exp`方法替代数组方式。
### 默认模板渲染规则改进
由于`fetch`方法和`view`函数的默认模板规则调整为操作方法的名称(不含操作后缀)转换为小写+下划线方式,而不是原来的直接把操作名称转小写。
举个例子,你的控制器操作方法名如果是`helloWorld`,之前版本使用:
```
$this->fetch();
// 或者
view();
```
渲染输出的时候会定位到 `helloworld.html`模板文件,而新版会自动定位到`hello_world.html`模板文件。
> 对于指定模板渲染的`fetch`方法和`view`助手函数不受影响,对于非驼峰操作方法名也没有影响。
## 从`5.1.0`升级到`5.1.5`
从`5.1.0`版本可以无缝升级到`5.1.5`(包含以下任何一个版本)。
## 从`5.0`升级到`5.1`
由于`5.1`版本很多用法不同于`5.0`版本,本篇内容帮助你更顺利的从`5.0`版本迁移到`5.1`版本。
> 如非必要,在建项目请勿盲目升级,5.0版本依然持续维护中。
### 命名空间调整
如果你自定义了应用类库的命名空间,需要改为设置环境变量`APP_NAMESPACE`而不是应用配置文件,如果你使用了`.env`配置文件,可以在里面添加:
```
APP_NAMESPACE = 你的应用类库根命名空间名
```
然后,检查你的应用类库中`use`或者调用的系统类库,如果使用了下面的系统类库(主要涉及的类库是`5.0`静态调用的系统类库),那么命名空间需要调整如下:
5.0系统5.1系统think\\Appthink\\facade\\App (或者 App )think\\Cachethink\\facade\\Cache (或者 Cache )think\\Configthink\\facade\\Config (或者 Config )think\\Cookiethink\\facade\\Cookie (或者 Cookie )think\\Debugthink\\facade\\Debug (或者 Debug )think\\Envthink\\facade\\Env (或者 Env )think\\Hookthink\\facade\\Hook (或者 Hook )think\\Langthink\\facade\\Lang (或者 Lang )think\\Logthink\\facade\\Log (或者 Log )think\\Requestthink\\facade\\Request (或者 Request )think\\Responsethink\\facade\\Response (或者 Response )think\\Routethink\\facade\\Route (或者 Route )think\\Sessionthink\\facade\\Session (或者 Session )think\\Urlthink\\facade\\Url (或者 Url )think\\Validatethink\\facade\\Validate (或者 Validate )think\\Viewthink\\facade\\View (或者 View )> 如果只是用于依赖注入则无需更改命名空间。
后面括号里面的类名使用是的根命名空间(`\`),这是因为5.1对常用的系统核心类库做了类库别名,举个例子,如果应用类库开头`use`了 `think\Url`
```
use think\Url;
Url::build('index/index');
```
则需要改成
```
use think\facade\Url;
Url::build('index/index');
```
或者
```
use Url;
Url::build('index/index');
```
> 5\.1为系统的类库注册了类库别名,因此可以直接从根命名空间方式调用Url。
所以路由配置文件在迁移到`5.1`版本后你可以直接删除下面的一行代码
```
use think\Route;
```
### 配置文件调整
原有的配置文件`config.php`从应用目录移动到和应用目录同级的`config`目录,并拆分为`app.php`、`cache.php` 等独立配置文件,系统默认的配置文件清单如下:
配置文件说明app.php应用配置文件cache.php缓存配置文件cookie.phpCookie配置文件database.php数据库配置文件log.php日志配置文件session.phpSession配置文件template.php模板引擎配置文件trace.php页面Trace配置文件> 换而言之就是原来所有的一级配置都独立为一个配置文件
原来的应用`extra`目录下面的配置文件直接移动到`config`目录下面。
原来模块的配置文件(包括extra目录下面的)直接移动到模块下的`config`目录,然后参考上面的应用配置文件进行调整。
5\.1的配置文件全部采用二级配置方式,所有**不带一级配置名的参数都会作为`app`的二级配置**,例如
```
config('app_debug');
```
等同于
```
config('app.app_debug');
```
> 并且注意,5.1的二级配置参数区分大小写。
一级配置`app`下的配置参数都在`app.php`配置文件中定义。
如果要获取数据库配置(`database.php`文件)的参数,则需要使用
```
config('database.hostname');
```
动态设置配置参数的时候,也要注意一级配置名
```
config('cache.type', 'memcache');
```
如果要获取一级配置下面的所有参数,使用
```
Config::pull('database');
```
`view_replace_str`配置参数改成template配置文件的`tpl_replace_string`配置参数。
### 常量调整
`5.1`取消了所有的框架内置常量(不影响应用代码中的自定义常量),如需获取,请使用`think\facade\App`类的内置方法以及`think\facade\Env`类获取,下面给出的是`5.0`和`5.1`的常量对照表:
5.0常量5.1获取方法EXT取消,固定使用 `.php`IS\_WIN取消IS\_CLI取消DS使用PHP自带 `DIRECTORY_SEPARATOR`ENV\_PREFIX取消,固定使用`PHP_`THINK\_START\_TIME`App::getBeginTime()`THINK\_START\_MEM`App::getBeginMem()`THINK\_VERSION`App::version()`THINK\_PATH`Env::get('think_path')`LIB\_PATH`Env::get('think_path') . 'library/'`CORE\_PATH`Env::get('think_path') . 'library/think/'`APP\_PATH`Env::get('app_path')`CONFIG\_PATH`Env::get('config_path')`CONFIG\_EXT`App::getConfigExt()`ROOT\_PATH`Env::get('root_path')`EXTEND\_PATH`Env::get('root_path') . 'extend/'`VENDOR\_PATH`Env::get('root_path') . 'vendor/'`RUNTIME\_PATH`Env::get('runtime_path')`LOG\_PATH`Env::get('runtime_path') . 'log/'`CACHE\_PATH`Env::get('runtime_path') . 'cache/'`TEMP\_PATH`Env::get('runtime_path'). 'temp/'`MODULE\_PATH`Env::get('module_path')`通过`Env`类的`get`方法获取路径变量的时候不区分大小写,例如下面的写法是等效的:
```
Env::get('root_path');
Env::get('ROOT_PATH');
```
### 路由调整
原有的路由定义文件`route.php` 移动到应用目录同级的`route`目录下面,如果有定义其它的路由配置文件,一并放入`route`目录即可(无需更改文件名)。
`url_route_on`配置参数无效,会始终检查路由,没有定义路由的情况下默认解析方式依然有效。
原来的`before_behavior`和`after_behavior`参数更改为`before`和`after`,并且路由缓存功能暂时取消。
Route类的`rule`方法不再支持批量注册路由,请使用`Route::rules`方法替代。
如果使用了domain方法批量绑定模块,需要改为单独绑定,原来的用法:
```
Route::domain([
'a' => 'a',
'b' => 'b'
]);
```
需要改为:
```
Route::domain('a','a');
Route::domain('b','b');
```
### 数据库调整
- 取消了Query类的`getTableInfo`方法,可以用更加具体的`getTableFields`
或者`getFieldsType`方法替代;
- 数据库查询后`5.1`不会清空查询条件;
- 取消了`select(false)` 用法,使用 `fetchSql()->select()` 替代;
- 如果使用了mysql的JSON查询语法,`user$.name` 需要改为 `user->name`;
- 改变了查询构造器的数组多字段批量查询,从原来的
```
where([
'name' => ['like','think%'],
'id' => ['>',0],
])
```
需要调整为
```
where([
['name','like','think%'],
['id','>',0],
])
```
或者使用表达式语法
```
where('name','like','think%')->where('id','>',0)
```
对于纯等于的数组条件则无需调整
```
where(['name'=>'think', 'type'=>1])
```
### 模型调整
为了确保模型的用法统一,对模型进行了一些调整,包括:
- 模型的数据集查询始终返回数据集对象而不再是数组;
- 模型的数据表主键如果不是`id`,则必须设置模型的`pk`属性;
- 软删除trait引入更改为 `use think\model\concern\SoftDelete`;
- 全局查询范围`base`方法中无需添加软删除条件;
- 聚合模型功能废除,使用关联模型配合关联自动写入功能替代,更灵活;
- 模型的查询范围`scope`方法调用后只能使用数据库的查询方法;
- 取消模型的数据验证功能,请使用控制器验证或者路由验证替代;
### 控制器调整
为了规范化,继承了`think\Controller`类的话,初始化方法从原来的`_initialize`方法更改为`initialize`。
`fetch`方法以及`view`助手函数的`replace`参数废弃,如果需要模板替换功能,改成template配置文件的`tpl_replace_string`配置参数。或者使用`filter`方法进行过滤。
### 官方扩展
官方的下列`composer`扩展请升级到最新的`2.0`版本:
```
topthink/think-captcha
topthink/think-mongo
topthink/think-migration
topthink/think-testing
topthink/think-queue
```
### 其它注意事项
`Request`类不再需要`instance`方法,直接调用类的方法即可。
废弃了`Rest`控制器扩展,建议更改为资源控制器的方式。
原来内置的其它控制器扩展,请自行在应用里面扩展。
因为严格遵循`PSR-4`规范,不再建议手动导入类库文件,所以新版取消了`Loader::import`方法以及`import`和`vendor`助手函数,推荐全面采用命名空间方式的类以及自动加载机制,如果必须使用请直接改为php内置的`include`或者`require`语法。
为了保持`Loader`类库的单纯性,原`Loader`类的`controller`、`model`、`action`和`validate`方法改为`App`类的同名方法,助手函数用法保持不变。
模板的变量输出默认添加了`htmlentities`安全过滤,如果你需要输出html内容的话,请使用`{$var|raw}`方式替换,并且`date`方法已经做了内部封装,无需再使用`###`变量替换了。
> ### 最后一个步骤不要忘了:清空缓存目录下的所有文件
- 序言
- 基础
- 安装
- 开发规范
- 目录结构
- 配置
- 架构
- 架构总览
- 入口文件
- URL访问
- 模块设计
- 命名空间
- 容器和依赖注入
- Facade
- 钩子和行为
- 中间件
- 路由
- 路由定义
- 变量规则
- 路由地址
- 闭包支持
- 路由参数
- 路由缓存
- 跨域请求
- 注解路由
- 路由分组
- MISS路由
- 资源路由
- 快捷路由
- 路由别名
- 路由绑定
- 域名路由
- URL生成
- 控制器
- 控制器定义
- 前置操作
- 跳转和重定向
- 空操作和空控制器
- 分层控制器
- 资源控制器
- 请求
- 请求对象
- 请求信息
- 输入变量
- 请求类型
- HTTP头信息
- 伪静态
- 参数绑定
- 请求缓存
- 响应
- 响应输出
- 响应参数
- 重定向
- 数据库
- 连接数据库
- 查询构造器
- 查询数据
- 添加数据
- 更新数据
- 删除数据
- 查询表达式
- 链式操作
- 聚合查询
- 时间查询
- 高级查询
- 视图查询
- JSON字段
- 子查询
- 原生查询
- 查询事件
- 事务操作
- 监听SQL
- 存储过程
- 数据集
- 分布式数据库
- 模型
- 定义
- 新增
- 更新
- 删除
- 查询
- JSON字段
- 获取器
- 修改器
- 自动时间戳
- 只读字段
- 软删除
- 类型转换
- 数据完成
- 查询范围
- 模型输出
- 模型事件
- 模型关联
- 一对一关联
- 一对多关联
- 远程一对多
- 多对多关联
- 多态关联
- 关联预载入
- 关联统计
- 关联输出
- 视图
- 视图渲染
- 视图赋值
- 视图过滤
- 模板引擎
- 模板
- 变量输出
- 使用函数
- 运算符
- 原样输出
- 模板注释
- 模板布局
- 模板继承
- 包含文件
- 输出替换
- 标签库
- 内置标签
- 循环标签
- 比较标签
- 条件判断
- 资源文件加载
- 标签嵌套
- 原生PHP
- 定义标签
- 标签扩展
- 错误和日志
- 异常处理
- 日志处理
- 调试
- 调试模式
- Trace调试
- 性能调试
- SQL调试
- 变量调试
- 远程调试
- 验证
- 验证器
- 验证规则
- 错误信息
- 验证场景
- 路由验证
- 内置规则
- 独立验证
- 静态调用
- 表单令牌
- 杂项
- 缓存
- Session
- Cookie
- 多语言
- 分页
- 上传
- 命令行
- 启动内置服务器
- 自动生成目录结构
- 创建类库文件
- 生成类库映射文件
- 清除缓存文件
- 生成配置缓存文件
- 生成数据表字段缓存
- 生成路由映射缓存
- 自定义指令
- 扩展库
- 验证码
- 图像处理
- Time
- 数据库迁移工具
- Workerman
- MongoDb
- 单元测试
- 安全和性能
- 安全建议
- 优化建议
- 附录
- 助手函数
- 升级指导
- 更新日志