在thinkphp中有两种常见的操作方式,一种是用Db对象来操作,一种则是用model类来操作数据库。下面都会进行介绍
save,update (增改)
insertGetId ,返回主键,save中有自增主键id,那么就是变成更新
$id = Db::name('role_user')->insertGetId(['role_id'=> 1,'user_id'=>2]);
$flag = Db::name('role_user')->save(['id'=>$id,'role_id'=> 1,'user_id'=>2]);
这种写法对Db有效,如果是model来操作,是先find(主键),然后save.
批量save
$data = Request::param();
$persons = $data['persons']??[];
if($persons){
$t = new Person();
$t->saveAll($persons);
}
Db::name('user')->insertAll([['name'=>'lily','age'=>16],['name'=>'larry','age'=>20]]);
left join
$where['vru.user_id'] = $userId ;
$field= ['role_grade'] ;
$role = Db::name("role")->alias('vr')
->leftJoin('v_role_user vru ',' vr.id=vru.role_id' )
->where($where)->field($field)->find() ;
if(!is_null($role)){
$grade=$role['role_grade'];
}
in
$grade=4;
$role = Db::name('role')
->where(['role_grade'=> $grade-1,'id'=>array(1,2,3)])
->field('id')->find();
if(is_null($role)){
return 'k';
}else{
// return $role;
return json($role['id']);
}
在php中,如果 => 右边的是数组,那么会被识别成 in, 否则是 =
search (查询)
$role = Db::query('select vr.id from v_role vr left join v_role_user vru on vru.role_id=vr.id where vru.user_id='.$userId);
return $role[0]['id']; // 注意query方法是查数组
其他操作
如!=
$data = Db::name('user')->where($where)->where('id','<>',1)->select();
delete
(一般软删除数据 使用delete_time字段标记删除)
Db::name('user')
->where('id', 1)
->useSoftDelete('delete_time',time())
->delete();
这边是官方原代码,你如果也测试会发现根本没用,而且原理很简单,官方也是通过标记的方式做的。所以这个删除还是自己加标记字段,比如status 0 ,1 来判断是否删除,然后删除就是更新这个标记字段 ,框架支持有bug,性能也会差些。自己看吧。
其他经验:
调试
1.fetchSql写在select前面 可以返回sql.调试用
$re = Db::name("role")->fetchSql()->select();
不过还是建议使用官方的Log类来打日志调试,会效率更高。
use think\facade\{
Log
}
$index = ($params['page']-1) * $params['size'];
// Log::info('RRR'.$index.'--'.$params['page'].'--'.$params['size']);
$query = "select * from v_user where parent_id=".$userId." AND `v_user`.`delete_time` IS NULL order by create_time desc". " limit ".$index.",".$params['size'];
Log::info($query);
或者还可以使用xdebug 断点调试,不过不知道是不是我的php环境(phpstudy 搭建 php7.4.3)有问题,有时候进不去断点。
xdebug方式
- vscode安装php debug插件
php.ini文件添加
[XDebug]
zend_extension = D:\phpstudy_pro\Extensions\php\php7.3.4nts\ext\php_xdebug-3.0.3-7.3-vc15-nts-x86_64.dll
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_handler=dbgp
xdebug.romote_host=127.0.0.1
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_port = 9000
2.主键是自定义的字段名,使用model属性
class Group extends Model
{
protected $pk = 'group_id';
}
3.find() 找一个{},select找到集合 [{},{}],实际上find返回的东西也是数组,不过你可以把他认为前端的 {} 结构来使用他。
Array
(
[role] => 2
)
4.用过该框架都知道你如果设计表时候添加个create_time,update_time,并且设置类型是int,配置文件database.php
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
'auto_timestamp' => true,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
那么取出数据会自动变成日期,但是触发是通过模型的,db类则不生效
$re = Db::name("role")->select(); //时间戳不会变成日期
$re = MRole::select();
如果db查询不会转
当然插入自然也是model触发的
// Db::name('system_log')->save(['description'=>'测试']); 不生效
//生效
$log = new MSystemLog();
$log->description='测试2';
$log->save();
我们现在知道查询时间戳自动转日期,但是是通过模型的,但是有时候我们又想使用Db来写较复杂的语句时,怎么办?
查询进阶
$re = MRole::where(['creator'=>$userId])->where('role_grade','<=',
Db::name('role')->alias('vr')
->leftJoin('role_user vru','vru.role_id=vr.id')
->where('vru.user_id',$userId)->field('vr.role_grade as role')->find()['role']
)->select();
$count = count($re);
return json(['code'=>20000,'data'=> ['data'=>$re,'count'=>$count]]);
转成sql执行就是如下,刚开始也许看不太懂,不过学新东西都是这样,多看几次。
SELECT * FROM `v_role` WHERE `creator` = 53 AND `role_grade` <= (
SELECT vr.role_grade as role FROM `v_role` `vr` LEFT JOIN `v_role_user` `vru`
ON `vru`.`role_id`=`vr`.`id` WHERE `vru`.`user_id` = 53 LIMIT 1
)
v_是我配置的数据库表前缀,忽视就好。