### 2018 年 12 月 31 日 发布 本文内容主要介绍下ThinkPHP`5.2`目前版本的数据库和模型操作相对于`5.1`版本的一些变化区别。 总体来说,在数据库和模型层面,`5.2`的改动并不大,只是因为强类型变量的约束会导致一些用法的差异,以及一些统一和废弃的方法会导致查询代码的调整。 >[danger] `5.2`版本目前尚未正式发布,在正式发布之前可能仍然会存在变化。 ## 新特性 在`5.1`最新版本的基础上,改进和新增了一些功能特性。 ### 强类型严格模式 新版核心全面启用了严格模式,避免因为方法参数类型模糊而导致的规范不一或者潜在问题。 ### `Db`使用门面对象 新版的`Db`类不再是静态类,需要使用`think\facade\Db`门面进行静态代理。 ``` \think\facade\Db::name('user')->find(); ``` ### 重构的`fetchSql`方法 查询类的`fetchSql`方法返回了一个新的`think\db\Fetch`类,获取查询SQL的操作和查询操作完全隔离。另外一个副作用是可以使得查询方法的返回值更加规范。`Fetch`类目前已经支持动态查询方法。 ``` Db::name('user')->where('id', 1); // 返回\think\db\Query对象实例 Db::name('user')->where('id', 1)->fetchSql(); // 返回\think\db\Fetch对象实例 ``` ### 增加乐观锁功能 和软删除一样,增加了一个`think\model\concern\OptimLock`Trait用于方便引入扩展模型的乐观锁功能。 ``` <?php namespace app\index\model; use think\model\conern\OptimLock; use think\Model; class User extends Model { use OptimLock; protected $optimLock = 'lock_version'; } ``` ### 增加`fetchArray`方法 模型的查询可以通过显式调用`fetchArray`方法使得查询结果返回数组而不是模型对象和数据集,适用于一些图表控件的数据输出。 ``` // 返回模型对象 User::find(1); // 返回数组 User::fetchArray()->find(1); ``` ### 模型增加`Schema`定义 模型类增加`schema`属性,用于**完整定义**模型对应数据表的字段信息,可以避免查询的时候获取数据表字段信息而无需生成`Schema`缓存。并且该属性中定义字段类型支持使用`php`类型定义。需要注意和`field`/`type`属性的区别,field属性仅用于定义当前模型允许写入的字段,而`type`属性则仅用于定义数据字段的类型强制转换。 ``` <?php namespace app\index\model; use think\Model; class User extends Model { protected $schema = [ 'id' => 'int', 'name' => 'string', 'score' => 'float', 'create_time' => 'datetime', 'update_time' => 'datetime', 'delete_time' => 'datetime', ]; } ``` ### 模型延迟保存机制 模型增加延迟保存方法`lazySave`,调用该方法后不会马上保存数据,仅仅是保存在内存中,当前模型对象销毁的时候或者下次显式调用`save`方法的时候都会自动保存到数据库。 ``` $user = User::find(1); $user->name = 'thinkphp'; $user->lazySave(); ... $user->score = 100; $user->save(); ``` ### `join`系列方法增加参数绑定支持 `join`方法(包括`leftJoin`/`rightJoin`/`fullJoin`方法)支持手动参数绑定。 ### 增加`tableRaw`方法 增加`tableRaw`方法使用表达式方法定义当前查询的数据表。 ### 查询缓存支持闭包情况 改进查询缓存方法支持使用闭包查询的情况。 ### 增加`withAttrs`方法 由于参数强制类型的关系,`withAttr`方法不支持传入数组,必须使用`withAttrs`方法传入数组批量设置字段获取器。 ## 废弃功能和方法 废弃了一些目前已经很少用到或者不建议使用的功能,以及对容易混淆的一个功能多个用法进行了统一。 ### 数据分表功能 取消了数据库分表功能,建议直接使用数据库的分区功能替代,更灵活和性能更好,同时取消了`Query`类的`getPartitionTableName`和`partition`方法。 ### 取消了`get`/`all`方法 无论使用`Db`类还是模型类查询,全部统一使用`find`/`select`方法,取消了之前模型类额外提供的`get`/`all`方法。 ### 取消`findOrEmpty`方法 取消了Query类的`findOrEmpty`方法,当模型使用`find`方法查询的时候,数据不存在自动返回一个空模型对象,无需再使用`findOrEmpty`方法了。 ### 取消`relation`方法 取消了Query类的`relation`方法,模型的关联获取直接使用关联属性方式惰性获取。 ### 取消了`readMaster`方法 取消了Query类和模型类的`readMater`方法,由于该方法使用了静态属性容易导致Swoole等常驻内存的环境下读取错乱。需要的时候可以用`master`方法手动切换主库读取。 ### 取消`fetchPdo`方法 取消了Query类的`fetchPdo`方法,需要的时候直接使用`getPdo`方法替代。 ### 取消查询方法传入`Query`对象 取消Query类的CURD查询方法传入当前对象,如果需要请使用闭包替代。 ### 取消全局查询范围`base`方法 取消模型类的全局查询范围`base`方法,改由使用`globalScope`属性定义(数组)需要全局查询的查询范围方法。或者在`db($scope)`方法中传入全局查询范围。如果是静态查询,可以使用`useGlobalScope($scope)`。 ### 取消`db`和`model`助手函数 这两个助手函数`5.1`版本已经不再建议使用了,新版直接废弃掉这两个助手函数,请指教使用`\think\facade\Db`类和实际的模型类调用。 ### 取消`setInc`/`setDec`方法 取消Query类的`setInc`/`setDec`方法,统一使用`inc`/`dec`方法替代,同时改进了`inc`/`dec`方法支持延时更新。 ## 取消`setField`方法 取消Query类的`setField`方法,请直接使用`data`方法或者`update`方法。 ### 取消`__TABLE_NAME__`支持 `table`方法取消`__TABLE_NAME__`支持,必须明确调用完整表名或者使用`name`方法。 ### 取消`whereOr`等方法传入`Query`对象 除了`where`方法本身可以传入`Query`对象外,其它的所有`where`查询方法(例如`whereOr`/`whereExp`等)都不再支持传入`Query`对象。 ### 取消`resultset_type`配置参数 数据集查询结果不再受`resultset_type`配置参数影响,默认情况下,Db查询统一返回数组,模型查询统一返回模型对象和模型数据集对象。如果Db查询的时候也需要返回数据集的话,可以显式调用`fetchCollection`方法。 ### `with`方法和`withJoin`独立 无需在模型关联方法中定义是否使用JOIN查询,只有在明确调用`withJoin`的时候才会使用JOIN查询。