6.0框架的ORM库基于官方的独立think-orm库,该类库基于PHP7.1+,并且内置支持包括MySQL、Sqlite、Pgsql、Sqlsrv、Oracle以及MongoDb驱动。所以,必要的时候你需要单独更新think-orm库而不是仅仅更新核心框架。
数据库
新版数据库配置文件采用多类型配置,方便切换数据库连接。如果要增加数据库连接,只需要在database.php配置文件中的connections配置项中新增即可。
建议使用查询构造器进行数据库操作,提供了较为直观的语义化查询。例如:
Db::name('user')
->field('id,name')
->where('name', 'think')
->whereOr('name', 'php')
->order('id', 'desc')
->limit(10)
->select();
select查询用于查询多条数据,并始终返回数据集对象(没错,无论是Db查询还是模型查询,新版都是返回数据集对象,并且废弃了数据集查询返回类型的设置),提供了和数组几乎无差异的用法。
$list = Db::name('user')->field('id,name')->select();
$count = count($list);
foreach($list as $user) {
echo $user['id'] . ':' . $user['name'];
}
需要注意的是当没有查询结果的时候,返回的是一个空的数据集对象而不是Null。
不要使用empty函数来判断数据集是否为空,而应该使用数据集对象的isEmpty方法。
$list = Db::name('user')->field('id,name')->select();
if(empty($list)) {// 错误
}
if($list->isEmpty()) {// 正确
}
查询单个数据使用find方法
$user = Db::name('user')->field('id,name')->find(1);
if($user) {
echo $user['id'] . ':' . $user['name'];
}
find查询如果数据不存在返回Null,所以需要判断下返回结果再做操作。
如果find查询不带任何条件并且也没有调用order方法的话,不会有任何结果。
可以使用findOrFail查询当数据不存在的话就会抛出异常
$user = Db::name('user')->field('id,name')->findOrFail(1);
echo $user['id'] . ':' . $user['name'];
如果只是需要取一列数据,可以使用column查询。
$names = Db::name('user')->column('name');
foreach($names as $name) {
echo $name;
}
或者指定索引
$names = Db::name('user')->column('name', 'id');
foreach($names as $id => $name) {
echo $id . ':' . $name;
}
获取某个数据的指定字段的值可以用value查询
$name = Db::name('user')->where('id', 1)->value('name');
为了减轻数据库的压力,对于一些实时性要求不高的数据可以使用查询缓存,只需要简单的调用cache方法即可,例如:
$list = Db::name('user')->field('id,name')
->cache(30) // 指定30秒的数据缓存
->select();
所有的查询方法都可以支持,如果你对数据进行了修改,也可以利用cache方法自动更新查询缓存,更多用法建议参考完全手册的cache方法。
如果要对数据进行写入,最简单的是使用save方法,你不需要关注新增还是更新,系统会自动判断。
Db::name('user')->save([
'id' => 1,
'name' => 'think',
]);
如果数据中包含主键或者使用了where方法,则会自动进行更新操作(update),否则会认为是新增(insert)。
你也可以使用insert方法新增数据和用update方法更新数据。
Db::name('user')->insert([
'id' => 1,
'name' => 'think',
]);
要删除数据使用
Db::name('user')->where('id', 1)->delete();
如果删除条件是主键的话,建议直接使用
Db::name('user')->delete(1);
使用connect方法切换不同的数据库连接查询数据
Db::connect('db_config')->name('user')->where('id', 1)->find();
注意,新版的 connect方法不支持动态设置数据库链接,也就是不再支持传入数组。
数据库每次查询的时候,会使用自动参数绑定以确保安全性(所以,基本上除非你使用原生查询,否则不需要进行手动参数绑定),但会有一条额外的查询来确定当前数据表的字段类型,但可以通过指令来生成字段缓存。
php think optimize:schema
字段缓存只有在关闭数据库的调试模式后有效。
如果要使用事务,可以简单的使用
Db::transaction(function () {
Db::name('order')->where('id', 1)->update(['status' => 1]);
Db::name('product')->where('order_id', 1)->inc('number',1)->update();
...
});
全部操作完成后,事务会自动提交,如果在闭包内抛出了任何异常,事务都会自动回滚,更多事务用法参考完全开发手册。
新版的查询语法更加强大,引入了一些新的快捷查询方法,包括时间查询(支持年月日周)、DUPLICATE及FIND IN SET查询,对JSON字段的查询也做了改进。
模型
除了在控制台指令中,推荐使用模型来替代数据库Db类操作。模型内置的查询和事务支持已经非常强大,而且完全可以使用数据库的查询构造器,也就是说Db类的所有功能模型都有,而且模型还提供了诸如自动时间戳、获取器、修改器、搜索器、模型关联及模型事件等功能,而且对象化操作的优势明显。
模型和数据表是一一对应的,一个模型对象对应一个数据表,而一个模型对象实例则对应数据表的一行数据。一个最简单的模型定义如下:
<?php
namespace app\model;
use think\Model;
class User extends Model
{
}
User模型会自动对应数据库的user数据表(如果有定义前缀的话还需要加上数据表前缀)。如果你的数据表主键统一使用id作为规范的话,模型不需要任何的额外代码就可以正常运作了。
$user = User::find(1);
$user->name = 'thinkphp';
$user->save();
如果你的主键不是id,一定记得要设置pk属性
<?php
namespace app\model;
use think\Model;
class User extends Model
{
protected $pk = 'user_id';
}
如果你的模型使用了类后缀,必须设置name属性,例如:
<?php
namespace app\model;
use think\Model;
class UserModel extends Model
{
protected $name = 'user';
}
由于参数自动绑定的需要,在查询的时候会因为判断当前模型字段的类型而多一次查询,如果需要更高的性能,可以在模型类里面定义schema属性,这样可以减少一次数据表的字段信息查询(如果你已经通过指令生成了字段缓存,则无需再次定义)。
<?php
namespace app\model;
use think\Model;
class User extends Model
{
protected $schema = [
'id' => 'int',
'name' => 'string',
'create_time' => 'datetime',
'update_time' => 'datetime',
];
}
如果你的模型使用的不是默认的数据库连接,则需要设置connection属性,指定需要连接的数据库连接标识。
<?php
namespace app\model;
use think\Model;
class User extends Model
{
protected $connection = 'db_config';
}
connetion属性不再支持数组,你必须事先在数据库配置文件中定义好数据库连接信息。
模型也可以进行数据集的查询,返回的是一个模型数据集对象,操作方式几乎和数组一致,可以直接遍历。
$list = User::select();
foreach ($list as $user) {
echo $user->id . ':' . $user->name;
}
由于使用了ArrayAccess接口,所以你可以用数组的方式获取模型属性,例如:
$list = User::select();
foreach ($list as $user) {
echo $user['id'] . ':' . $user['name'];
}
不要对模型数据集对象使用empty函数判断,而应该使用数据集的isEmpty方法
$list = User::select();
if(empty($list)) {// 错误
}
if($list->isEmpty()) {// 正确
}
如果要查询单个数据,应该使用find方法,
$user = User::find(1);
如果数据不存在,则返回Null,如果需要返回空的模型,可以使用
$user = User::findOrEmpty(1);
如果希望数据不存在的时候抛出异常可以使用
$user = User::findOrFail(1);
默认开启时间戳字段,并且会自动识别时间字段类型,对于不需要使用时间字段的模型,需要在模型里面单独关闭。
<?php
namespace app\model;
use think\Model;
class User extends Model
{
protected $autoWriteTimestamp = false;
}
模型和数据库类一样可以支持事务,方法是
User::transaction(function() {
// 模型操作代码
});
或者手动进行事务管理
// 启动事务
$db = $this->db();
$db->startTrans();
try {
User::find(1);
Profile::delete(1);
// 提交事务
$db->commit();
} catch (\Exception $e) {
// 回滚事务
$db->rollback();
}
不过,如果你使用了模型关联操作的话,大部分操作以及内置实现了事务支持,包括saveAll方法。
前提是需要使用同一个数据库连接(对象),或者配置了相同的数据库链接信息。
发表评论