TP6中数据库操作
TP6中数据库操作
要使用Db类必须使用门面方式(think\facade\Db)调用
use think\facade\Db;
一、数据库连接配置
配置文件位于,config/database.php
或者开发环境 位于根目录下的 .env 文件
APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai [DATABASE] TYPE = mysql //数据库类型 HOSTNAME = 127.0.0.1 //连接地址 DATABASE = test //数据库名称 USERNAME = username //数据库用户名 PASSWORD = password //数据库密码 HOSTPORT = 3306 //端口 CHARSET = utf8 //字符集 DEBUG = true //是否开启debug [LANG] default_lang = zh-cn
动态配置数据库连接查询
\think\facade\Db::connect('demo')->table('user')->find();
数据模型中定义connection属性
protected $connection = 'demo';
ThinkPHP的数据库连接是惰性的,只有实际的数据操作的时候才会去连接数据库。
二、数据库分布式支持
如果需要支持分布式数据库,包括读写分离,需要设置配置参数 deploy 的值为 1
// 启用分布式数据库 'deploy' => 1, 'hostname' => '192.168.1.1,192.168.1.2', //默认情况下第一个地址就是主服务器 // 数据库用户名 'username' => 'root,slave,slave', // 数据库密码 'password' => '123456',
关于 hostname,username,password,hostport,database,dsn,charset 要么值相同就配置一个,不然就分别设置
建议使用数组定义参数,例如:
'hostname' =>[ '192.168.1.1','192.168.1.2','192.168.1.3'], 'password' => ['123456','abc,def','hello']
三、数据库支持读写分离
开启读写分类配置:
'rw_separate' => true,
默认第一个是主数据库,负责写入数据。如果设置 master_num ,则可以支持多个主服务器写入。
如果用原生SQL,写操作必须用 execute 方法,读操作必须用 query方法
刚写入数据之后,从库数据还没来得及同步完成,你可以使用 master() 进行主库查询
Db::name('user')->master(true)->find(1);
也可以开启:当我们对某个数据表进行了写操作,那么当前请求的后续所有对该表的查询都会使用主库读取
'read_master' => true,
四、链式操作
查询单个数据
Db::table('think_user')->where('id', 1)->find();
查询为空返回空数组
Db::table('think_user')->where('id', 1)->findOrEmpty();
说明:
如果没有任何的查询条件,也没有调用order方法的话 ,find查询不会返回任何结果。
查询结果集:
Db::table('think_user')->where('status', 1)->select();
select 方法查询结果是一个数据集对象,如果需要转换为数组可以使用
Db::table('think_user')->where('status', 1)->select()->toArray();
查询一个字段
Db::table('think_user')->where('id', 1)->value('name');
查询一列
// 返回数组 Db::table('think_user')->where('status',1)->column('name'); // 指定id字段的值作为索引 Db::table('think_user')->where('status',1)->column('name', 'id');
添加数据:
$data = ['foo' => 'bar', 'bar' => 'foo']; Db::name('user')->save($data); 或 Db::name('user')->insert($data);
使用save方法时,数据中有ID则为更新,没有ID则为新增
insert 方法添加数据成功返回添加成功的条数,通常情况返回 1
如果不希望因为存在数据表中没有的字段而抛出异常,可以使用以下方法
Db::name('user')->strict(false)->insert($data);
添加后返回主键
$userId = Db::name('user')->strict(false)->insertGetId($data);
更新数据:
Db::name('user')->save(['id' => 1, 'name' => 'thinkphp']);
或
Db::name('user')->where('id', 1)->update(['name' => 'thinkphp']);
支持表达式更新
Db::name('user')->where('id',1)->exp('name','UPPER(name)')->update(); 或使用raw Db::name('user')->where('id', 1)->update([ 'name' => Db::raw('UPPER(name)'), 'score' => Db::raw('score-3'), 'read_time' => Db::raw('read_time+1') ]);
自增自减
// score 字段加 1 Db::table('think_user')->where('id', 1)->inc('score')->update(); // score 字段加 5 Db::table('think_user')->where('id', 1)->inc('score', 5)->update(); // score 字段减 1 Db::table('think_user')->where('id', 1)->dec('score')->update(); // score 字段减 5 Db::table('think_user')->where('id', 1)->dec('score', 5)->update();
删除数据:
// 根据主键删除 Db::table('think_user')->delete(1); Db::table('think_user')->delete([1,2,3]); // 条件删除 Db::table('think_user')->where('id',1)->delete(); Db::table('think_user')->where('id','<',10)->delete();
没有任何条件调用delete会返回错误。如果确实需要删除所有数据,可以使用
// 无条件删除所有数据 Db::name('user')->delete(true);
查询表达式:
格式如下:
where('字段名','查询表达式','查询条件');
// = 等于 Db::name('user')->where('id','=',100)->select(); //<> 不等于 Db::name('user')->where('id','<>',100)->select(); //> 大于 Db::name('user')->where('id','>',100)->select(); //>= 大于等于 Db::name('user')->where('id','>=',100)->select(); //< 小于 Db::name('user')->where('id', '<', 100)->select(); <= 小于等于 Db::name('user')->where('id', '<=', 100)->select(); //[NOT] LIKE 模糊查询 Db::name('user')->where('name', 'like', 'thinkphp%')->select(); //[NOT] BETWEEN (不在)区间查询 Db::name('user')->where('id','between','1,8')->select(); //[NOT] IN (不在)IN 查询 Db::name('user')->where('id','in','1,5,8')->select(); 或 Db::name('user')->where('id','in',[1,5,8])->select(); //[NOT] NULL : Db::name('user')->where('name', null)->where('email','null') ->where('name','not null')->select();
链式操作示例:
Db::table('think_user') ->where('status',1) ->order('create_time') ->limit(10) ->select();
链式where条件:
//1、表达式条件 Db::table('think_user')->where('id','>',1)->where('name','thinkphp')->select(); //2、数组条件 Db::table('think_user')->where(['name'=>'thinkphp','status'=>1])->select(); //3、字符串条件 Db::table('think_user')->whereRaw('type=1 AND status=1')->select(); 或需要传入变量,配合预处理机制,确保更加安全 Db::table('think_user') ->whereRaw("id=:id and username=:name", ['id' => 1 , 'name' => 'thinkphp']) ->select();
链式table操作
Db::field('user.name,role.title') ->table([ 'think_user'=>'user', 'think_role'=>'role' ]) ->limit(10)->select();
链式alias操作,设置表的别名
Db::table('think_user') ->alias('a') ->join('think_dept b ','b.user_id= a.id') ->select();
field操作
Db::table('user')->field('id,title,content')->select(); 或使用别名 Db::table('user')->field('id,nickname as name')->select(); 或使用SQL函数 Db::table('user')->fieldRaw('id,SUM(score)')->select();
strict操作
提交了非法字段会抛出异常,可以在配置中关闭严格字段检查
'fields_strict' => false,
也可以临时关闭
// 关闭字段严格检查 Db::name('user')->strict(false)->insert($data);
limit操作
//获取满足要求的10个用户 Db::table('user')->where('status',1)->field('id,name')->limit(10)->select(); //limit方法也可以用于写操作,例如更新满足要求的3条数据: Db::table('user')->where('score',100)->limit(3)->update(['level'=>'A']); //分页查询,查询从第20行开始的10条数据 Db::table('article')->limit(20,10)->select();
page操作
// 查询第一页数据 Db::table('article')->page(1,10)->select(); // 查询第二页数据 Db::table('article')->page(2,10)->select();
order操作
//没有指定排序规则,默认 asc Db::table('user')->where('status', 1)->order('id')->select(); //指定排序规则 Db::table('user')->where('status', 1)->order('id', 'desc')->select();
group操作
通常用于结合合计函数,根据一个或多个列对结果集进行分组。
Db::table('user')->field('user_id,username,max(score)') ->group('user_id')->select(); 对多个字段进行分组 Db::table('user')->field('user_id,test_time,username,max(score)') ->group('user_id,test_time')->select();
having操作
Db::table('score') ->field('username,max(score)')->group('user_id') ->having('count(test_time)>3')->select();
join操作
INNER JOIN: 等同于 JOIN(默认的JOIN类型),如果表中有至少一个匹配,则返回行 LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行 RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行 FULL JOIN: 只要其中一个表中存在匹配,就返回行
//join 方式 Db::table('think_artist') ->alias('a') ->join('work w','a.id = w.artist_id') ->join('card c','a.card_id = c.id') ->select(); //left join 方式 Db::table('think_user') ->alias('a') ->leftJoin('word w','a.id = w.artist_id') ->select();
五、聚合查询
count:Db::table('think_user')->count(); max:Db::table('think_user')->max('score'); min:Db::table('think_user')->min('score'); avg: Db::table('think_user')->avg('score'); sum: Db::table('think_user')->sum('score');
六、分页查询
控制器代码:
// 查询状态为1的用户数据 并且每页显示10条数据 $list = Db::name('user')->where('status',1)->order('id', 'desc')->paginate(10); // 获取分页显示 $page = $list->render(); return view('index', ['list' => $list, 'page' => $page]);
HTML代码:
<div> <ul> {volist name='list' id='user'} <li> {$user.nickname}</li> {/volist} </ul> </div> {$page|raw}
获取总数据
// 获取总记录数 $count = $list->total();
分页后数据处理
$list = Db::name('user')->where('status',1)->order('id', 'desc') ->paginate()->each(function($item, $key){ $item['nickname'] = 'think'; return $item; });
模型中分页数据处理,无需return
$list = User::where('status',1)->order('id', 'desc')->paginate()->each(function($item, $key){ $item->nickname = 'think'; });
分页参数:
$list = Db::name('user')->where('status',1)->paginate([ 'list_rows'=> 20, 'query' => $data ]);
七、时间查询 whereTime
// 大于某个时间 Db::name('user')->whereTime('birthday', '>=', '1970-10-1')->select(); // 小于某个时间 Db::name('user')->whereTime('birthday', '<', '2000-10-1')->select(); // 时间区间查询 Db::name('user')->whereTime('birthday', 'between', ['1970-10-1', '2000-10-1']) ->select(); // 不在某个时间区间 Db::name('user')->whereTime('birthday', 'not between', ['1970-10-1', '2000-10-1']) ->select();
八、原生查询
V6.0.3+版本开始,原生查询仅支持Db类操作
query方法
Db::query("select * from think_user where status=:id", ['id' => 1]); //从主库读取 Db::query("select * from think_user where status=:id", ['id' => 1], true);
execute方法
Db::execute("update think_user set name='thinkphp' where status=1");
参数绑定
//问号占位符绑定 Db::query("select * from think_user where id=? AND status=?", [8, 1]); // 命名绑定 Db::execute("update think_user set name=:name where status=:status", ['name' => 'thinkphp', 'status' => 1]); //注意不支持对表名使用参数绑定
九:事务操作
使用事务处理的话,需要数据库引擎支持事务处理。比如 MySQL 的 MyISAM 不支持事务处理,需要使用 InnoDB 引擎。
最简单的事务闭包操作:
Db::transaction(function () { Db::table('think_user')->find(1); Db::table('think_user')->delete(1); });
手动运行事务:
// 启动事务 Db::startTrans(); try { Db::table('think_user')->find(1); Db::table('think_user')->delete(1); // 提交事务 Db::commit(); } catch (\Exception $e) { // 回滚事务 Db::rollback(); }
十:存储过程
//数据访问层调用存储过程 $resultSet = Db::query('call procedure_name'); foreach ($resultSet as $result) { } //存储过程可以支持输入和输出参数,以及进行参数绑定操作。 $resultSet = Db::query('call procedure_name(:in_param1,:in_param2,:out_param)', [ 'in_param1' => $param1, 'in_param2' => [$param2, PDO::PARAM_INT], 'out_param' => [$outParam, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 4000], ]);
数据集:
// 获取数据集 $users = Db::name('user')->select(); // 直接操作第一个元素 $item = $users[0]; // 获取数据集记录数 $count = count($users); // 遍历数据集 foreach($users as $user){ echo $user['name']; echo $user['id']; }
判断数据集是否为空,不能直接使用empty判断,而必须使用数据集对象的isEmpty方法判断,
$users = Db::name('user')->select(); if($users->isEmpty()){ echo '数据集为空'; }
但行好事,莫问前程!
本文来自博客园,作者:yangphp,转载请注明原文链接:https://www.cnblogs.com/ypeih/p/15509092.html