# ThinkPHP6.0 数据库链式操作
数据库提供的链式操作方法,可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的CURD操作。
* * *
## ThinkPHP6 数据库链式操作
* 数据库提供的链式操作方法,可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的`CURD`操作
* 带\*标识的表示支持多次调用
连贯操作 作用 支持的参数类型where*用于AND查询字符串、数组和对象table 用于定义要操作的数据表名称字符串和数组name 用于定义要操作的数据表名称字符串field*用于定义要查询的字段(支持字段排除)字符串和数组order*用于对结果排序字符串和数组limit 用于限制查询结果数量字符串和数字page 用于查询分页(内部会转换成limit)字符串和数字
## 一、表达式查询
* 表达式是SQL语句的条件
* 表达式不分大小写
* 表达式写在where里
表达式含义查询方法=等于<>不等于>大于>=大于等于<小于<=小于等于[NOT] LIKE模糊查询whereLike/whereNotLike[NOT] BETWEEN(不在)区间查询whereBetween/whereNotBetween[NOT] IN(不在)IN 查询 whereIn/whereNotIn[NOT] NULL查询字段是否(不)是NULLwhereNull/whereNotNull
`where`查询
* where方法在链式操作方法里面是最常用的方法,可以完成包括普通查询、表达式查询、快捷查询、区间查询、组合查询在内的条件查询操作
> \# 等于(=)
>
> $select = Db::table('shop\_goods')->where('id','=','1')->select();
>
> print\_r($select->toArray());
>
>
>
> \# 不等于(<>)
>
> $select = Db::table('shop\_goods')->where('id','select();
>
> print\_r($select->toArray());
>
>
>
> \# 大于(>)
>
> $select = Db::table('shop\_goods')->where('id','>','3')->select();
>
> print\_r($select->toArray());
>
>
>
> \# 大于等于(>=)
>
> $select = Db::table('shop\_goods')->where('id','>=','4')->select();
>
> print\_r($select->toArray());
>
>
>
> \# 小于(<)
>
> $select = Db::table('shop\_goods')->where('id','select();
>
> print\_r($select->toArray());
>
>
>
> \# 小于等于(<=)
>
> $select = Db::table('shop\_goods')->where('id','select();
>
> print\_r($select->toArray());
>
>
>
> \# 多where
>
> $select = Db::table('shop\_goods')
>
> ->where('id','>','3')
>
> ->where('id','<','8')
>
> ->select();
>
> print\_r($select->toArray());
>
>
>
> \# LIKE
>
> $select = Db::table('shop\_goods')->where('title','like','%连衣裙%')->select();
>
> print\_r($select->toArray());
>
>
>
> # NOT LIKE
>
> $select = Db::table('shop\_goods')->where('title','not like','%连衣裙%')->select();
>
> print\_r($select->toArray());
>
>
>
> \# BETWEEN
>
> $select = Db::table('shop\_goods')->where('id','between','6,10')->select();
>
> print\_r($select->toArray());
>
>
>
> # NOT BETWEEN
>
> $select = Db::table('shop\_goods')->where('id','not between',\[6,10\])->select();
>
> print\_r($select->toArray());
>
>
>
> \# IN
>
> $select = Db::table('shop\_goods')->where('id','in','4,7,10')->select();
>
> print\_r($select->toArray());
>
>
>
> # NOT IN
>
> $select = Db::table('shop\_goods')->where('id','not in',\[4,7,10\])->select();
>
> print\_r($select->toArray());
## 二、数据表
1、table 和 name
> \# 必须完整数据库名
>
> $select = Db::table('shop\_goods')->where('id','10')->select();
>
> print\_r($select->toArray());
>
> \# 数据库未设置前缀
>
> $select = Db::name('shop\_goods')->where('id','11')->select();
>
> print\_r($select->toArray());
>
> \# 数据库设置前缀,无前缀访问
>
> $select = Db::name('list')->where('id','12')->select();
>
> print\_r($select->toArray());
2、数据库前缀
数据库配置`database.php`
> return \[
>
> 'connections' => \[
>
> 'mysql' => \[
>
> // 数据库表前缀
>
> 'prefix' => Env::get('database.prefix', 'shop\_'),
>
> \]
>
> \]
>
> \];
## 三、返回值
1、`field `
* field 方法主要作用是标识要返回或者操作的字段,可以用于查询和写入操作
* 所有的查询方法都可以使用field方法
> \# 字符串
>
> $select = Db::table('shop\_goods')
>
> ->field('title,price,discount as d')
>
> ->where('status',1)
>
> ->select();
>
> print\_r($select->toArray());
>
>
>
> \# 数组
>
> $select = Db::table('shop\_goods')
>
> ->field(\[
>
> 'title',
>
> 'price',
>
> 'discount'=>'d'
>
> \])
>
> ->where('status',1)
>
> ->select();
>
> print\_r($select->toArray());
>
>
>
> \# 添加,只能添加这几个字段
>
> \# 多field
>
> $data = \[
>
> 'title' => '新商品',
>
> 'price' => 50,
>
> 'discount' => 8,
>
> 'add\_time' => 1576080000
>
> \];
>
> $insert = Db::table('shop\_goods')
>
> ->field('title')
>
> ->field('price')
>
> ->field('discount')
>
> ->field('add\_time')
>
> ->insert($data);
>
> print\_r($insert);
>
>
>
> \# 查询全部字段,速度较快
>
> $select = Db::table('shop\_goods')
>
> ->field(true)
>
> // ->field('\*')
>
> ->where('status',1)
>
> ->select();
>
> print\_r($select->toArray());
2、`withoutField`
* withoutField 方法作用 排除数据表中的字段
~~~
Db::table('shop_goods')->withoutField('id')->select();
~~~
3、`fieldRaw`
* fieldRaw 方法直接使用mysql函数
~~~
Db::table('shop_goods')->fieldRaw('id,sum(price)')->select();
~~~
## 四、排序
1、`order`方法用于对操作的结果排序或者优先级限制
* 默认正序
* asc 正序
* desc 倒序
> $select = Db::table('shop\_goods')
>
> ->field('title,price,id')
>
> ->where('status',1)
>
> ->order('price','DESC')
>
> ->order('id','DESC')
>
> ->select();
>
> print\_r($select->toArray());
2、`orderRaw`方法中使用mysql函数
> $select = Db::table('shop\_goods')
>
> ->field('title,price,id')
>
> ->where('status',1)
>
> ->orderRaw("field(title,'price','discount','stock')")
>
> ->select();
>
> print\_r($select->toArray());
## 五、分页
* `limit`方法主要用于指定查询和操作的数量
> $select = Db::table('shop\_goods')
>
> ->field('title,price,id')
>
> ->where('status',1)
>
> ->order('price','DESC')
>
> ->limit(3)
>
> ->select();
>
> print\_r($select->toArray());
>
>
>
> $select = Db::table('shop\_goods')
>
> ->field('title,price,id')
>
> ->where('status',1)
>
> ->order('price','DESC')
>
> ->limit(0,5)
>
> ->select();
>
> print\_r($select->toArray());
* `page`方法主要用于分页查询
> $select = Db::table('shop\_goods')
>
> ->field('title,price,id')
>
> ->where('status',1)
>
> ->order('price','DESC')
>
> ->page(1,5)
>
> ->select();
>
> print\_r($select->toArray());
## 六、聚合查询
* 聚合方法如果没有数据,默认都是0,聚合查询都可以配合其它查询条件
方法功能count 统计数量,参数是要统计的字段名(可选)max 获取最大值,参数是要统计的字段名(必须)min 获取最小值,参数是要统计的字段名(必须)avg 获取平均值,参数是要统计的字段名(必须)sum获取总数,参数是要统计的字段名(必须)
> // 统计数量,参数是要统计的字段名(可选)
>
> $select = Db::table('shop\_goods')->count();
>
> print\_r($select);
>
>
>
> // 获取最大值,参数是要统计的字段名(必须)
>
> $select = Db::table('shop\_goods')->max('id');
>
> print\_r($select);
>
>
>
> // 获取最小值,参数是要统计的字段名(必须)
>
> $select = Db::table('shop\_goods')->min('id');
>
> print\_r($select);
>
>
>
> // 获取平均值,参数是要统计的字段名(必须)
>
> $select = Db::table('shop\_goods')->avg('id');
>
> print\_r($select);
>
>
>
> // 获取总数,参数是要统计的字段名(必须)
>
> $select = Db::table('shop\_goods')->sum('id');
>
> print\_r($select);
## 七、搜索、排序示例
controller代码
> public function index(){
>
> $title = '商城';
>
> $login = '欧阳克';
>
> # 左侧菜单
>
> $menu = Db::table('shop\_menu')->where('fid',0)->select();
>
> $left = $menu->toArray();
>
> foreach($left as &$left\_v){
>
> $left\_v\['lists'\] = Db::table('shop\_menu')->where('fid',$left\_v\['id'\])->select();
>
> }
>
> # 右侧列表
>
> $param = Request::param();
>
> if(isset($param\['status'\]) && $param\['status'\] == 1){
>
> $where\['status'\] = 1;
>
> }else if(isset($param\['status'\]) && $param\['status'\] == 2){
>
> $where\['status'\] = 2;
>
> }else{
>
> $where = true;
>
> }
>
> $list = Db::table('shop\_goods')
>
> ->where($where)
>
> ->order('add\_time DESC')
>
> ->order('id DESC')
>
> ->select();
>
> $right = $list->toArray();
>
> foreach($right as &$right\_v){
>
> $right\_v\['cat'\] = Db::table('shop\_cat')->where('id',$right\_v\['cat'\])->value('name');
>
> }
>
> View::assign(\[
>
> 'title' => $title,
>
> 'login' => $login,
>
> 'left' => $left,
>
> 'right' => $right,
>
> 'status' => isset($param\['status'\]) ? $param\['status'\] : null
>
> \]);
>
> return View::fetch();
>
> }
view代码
>
>
>
>
>
>
>
>
> 全部
>
> 开启
>
> 关闭
>
>
>
>
>
> 搜索
>
>
>
>
## 八、分页示例
controller代码
> public function index(){
>
> $title = '商城';
>
> $login = '欧阳克';
>
> # 左侧菜单
>
> $menu = Db::table('shop\_menu')->where('fid',0)->select();
>
> $left = $menu->toArray();
>
> foreach($left as &$left\_v){
>
> $left\_v\['lists'\] = Db::table('shop\_menu')->where('fid',$left\_v\['id'\])->select();
>
> }
>
> # 右侧列表
>
> $param = Request::param();
>
> if(isset($param\['status'\]) && $param\['status'\] == 1){
>
> $where\['status'\] = 1;
>
> }else if(isset($param\['status'\]) && $param\['status'\] == 2){
>
> $where\['status'\] = 2;
>
> }else{
>
> $where = true;
>
> }
>
> $p = isset($param\['p'\]) ? $param\['p'\] : 1;
>
> // 统计总数
>
> $count = Db::table('shop\_goods')->where($where)->count();
>
> $list = Db::table('shop\_goods')
>
> ->where($where)
>
> ->order('add\_time DESC')
>
> ->order('id DESC')
>
> ->page($p,10)
>
> ->select();
>
> $right = $list->toArray();
>
> foreach($right as &$right\_v){
>
> $right\_v\['cat'\] = Db::table('shop\_cat')->where('id',$right\_v\['cat'\])->value('name');
>
> }
>
> View::assign(\[
>
> 'title' => $title,
>
> 'login' => $login,
>
> 'left' => $left,
>
> 'right' => $right,
>
> 'count' => ceil($count/10),
>
> 'p' => $p,
>
> 'status' => isset($param\['status'\]) ? $param\['status'\] : 0
>
> \]);
>
> return View::fetch();
>
> }
view代码
>
>
> 上一页
>
> {for start="0" end="$count"}
>
> {if $p == $i+1}
>
>
>
>
>
> {$i+1}
>
>
>
> {else/}
>
> {$i+1}
>
> {/if}
>
> {/for}
>
> =$count}layui-disabled{/if}">下一页
>
>
## 九、模版分页
* `paginate`内置了分页实现,要给数据添加分页输出功能变得非常简单
* `render`获取翻页html代码
* `total`获取总数量
controller代码
> $select = Db::table('shop\_goods')->paginate(10);
>
> print\_r($select);echo '';
>
> foreach($select as $v){
>
> print\_r($v);echo '';
>
> }
>
> print\_r($select->render());echo '';
>
> print\_r('总数:'.$select->total());echo '';
>
> View::assign(\[
>
> 'select' => $select
>
> \]);
>
> return View::fetch();
view代码
> {$select|raw}
css代码
> .pagination {
>
> display: inline-block;
>
> padding-left: 0;
>
> margin: 20px 0;
>
> border-radius: 4px;
>
> }
>
> .pagination > li {
>
> display: inline;
>
> }
>
> .pagination > li > a,
>
> .pagination > li > span {
>
> position: relative;
>
> float: left;
>
> padding: 6px 12px;
>
> margin-left: -1px;
>
> line-height: 1.42857143;
>
> color: #337ab7;
>
> text-decoration: none;
>
> background-color: #fff;
>
> border: 1px solid #ddd;
>
> }
>
> .pagination > li:first-child > a,
>
> .pagination > li:first-child > span {
>
> margin-left: 0;
>
> border-top-left-radius: 4px;
>
> border-bottom-left-radius: 4px;
>
> }
>
> .pagination > li:last-child > a,
>
> .pagination > li:last-child > span {
>
> border-top-right-radius: 4px;
>
> border-bottom-right-radius: 4px;
>
> }
>
> .pagination > li > a:hover,
>
> .pagination > li > span:hover,
>
> .pagination > li > a:focus,
>
> .pagination > li > span:focus {
>
> z-index: 2;
>
> color: #23527c;
>
> background-color: #eee;
>
> border-color: #ddd;
>
> }
>
> .pagination > .active > a,
>
> .pagination > .active > span,
>
> .pagination > .active > a:hover,
>
> .pagination > .active > span:hover,
>
> .pagination > .active > a:focus,
>
> .pagination > .active > span:focus {
>
> z-index: 3;
>
> color: #fff;
>
> cursor: default;
>
> background-color: #337ab7;
>
> border-color: #337ab7;
>
> }
>
> .pagination > .disabled > span,
>
> .pagination > .disabled > span:hover,
>
> .pagination > .disabled > span:focus,
>
> .pagination > .disabled > a,
>
> .pagination > .disabled > a:hover,
>
> .pagination > .disabled > a:focus {
>
> color: #777;
>
> cursor: not-allowed;
>
> background-color: #fff;
>
> border-color: #ddd;
>
> }
## 十、模版分页示例
参数描述list_rows 每页数量page 当前页pathurl路径query url额外参数fragment url锚点var_page 分页变量
controller代码
> public function index(){
>
> $title = '商城';
>
> $login = '欧阳克';
>
> # 左侧菜单
>
> $menu = Db::table('shop\_menu')->where('fid',0)->select();
>
> $left = $menu->toArray();
>
> foreach($left as &$left\_v){
>
> $left\_v\['lists'\] = Db::table('shop\_menu')->where('fid',$left\_v\['id'\])->select();
>
> }
>
> # 右侧列表
>
> $param = Request::param();
>
> if(isset($param\['status'\]) && $param\['status'\] == 1){
>
> $where\['status'\] = 1;
>
> }else if(isset($param\['status'\]) && $param\['status'\] == 2){
>
> $where\['status'\] = 2;
>
> }else{
>
> $where = true;
>
> }
>
> $p = isset($param\['p'\]) ? $param\['p'\] : 1;
>
> # thinkphp 自带分页
>
> $list = Db::table('shop\_goods')
>
> ->where($where)
>
> ->order('add\_time DESC')
>
> ->order('id DESC')
>
> ->paginate(\[
>
> 'list\_rows'=> 10,
>
> 'query' => Request::param()
>
> \]);
>
> $right = $list->toArray();
>
> foreach($right as &$right\_v){
>
> $right\_v\['cat'\] = Db::table('shop\_cat')->where('id',$right\_v\['cat'\])->value('name');
>
> }
>
> View::assign(\[
>
> 'title' => $title,
>
> 'login' => $login,
>
> 'left' => $left,
>
> 'right' => $right,
>
> 'list' => $list,
>
> 'status' => isset($param\['status'\]) ? $param\['status'\] : 0
>
> \]);
>
> return View::fetch();
>
> }
view代码
> {$paginate|raw}
## 十一、SQL 调试
* `getLastSql`输出上次执行的sql语句
* `getLastSql`方法只能获取最后执行的 SQL 记录
~~~
$select = Db::table('shop_goods')->select();
echo Db::getLastSql();
~~~
* `fetchSql`方法直接返回当前的 SQL 而不执行
~~~
$select = Db::table('shop_goods')->fetchSql()->select();
echo $select;
~~~
## 十二、动态配置数据库
* config目录database.php文件
> return \[
>
> 'connections' => \[
>
> 'ouyangke' => \[
>
> // 数据库类型
>
> 'type' => Env::get('database.type', 'mysql'),
>
> // 服务器地址
>
> 'hostname' => Env::get('database.hostname', '127.0.0.1'),
>
> // 数据库名
>
> 'database' => 'ouyangke',
>
> // 用户名
>
> 'username' => Env::get('database.username', 'root'),
>
> // 密码
>
> 'password' => Env::get('database.password', 'root'),
>
> // 端口
>
> 'hostport' => Env::get('database.hostport', '3306'),
>
> // 数据库连接参数
>
> 'params' => \[\],
>
> // 数据库编码默认采用utf8
>
> 'charset' => Env::get('database.charset', 'utf8'),
>
> // 数据库表前缀
>
> 'prefix' => Env::get('database.prefix', 'shop\_'),
>
> // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
>
> 'deploy' => 0,
>
> // 数据库读写是否分离 主从式有效
>
> 'rw\_separate' => false,
>
> // 读写分离后 主服务器数量
>
> 'master\_num' => 1,
>
> // 指定从服务器序号
>
> 'slave\_no' => '',
>
> // 是否严格检查字段是否存在
>
> 'fields\_strict' => true,
>
> // 是否需要断线重连
>
> 'break\_reconnect' => false,
>
> // 监听SQL
>
> 'trigger\_sql' => true,
>
> // 开启字段缓存
>
> 'fields\_cache' => false,
>
> // 字段缓存路径
>
> 'schema\_cache\_path' => app()->getRuntimePath() . 'schema' . DIRECTORY\_SEPARATOR,
>
> \]
>
> \]
>
> \];
* ouyangke数据库中的shop\_user表
> CREATE TABLE `shop\_user` (
>
> `uid` int(10) unsigned NOT NULL AUTO\_INCREMENT COMMENT '用户ID',
>
> `account` varchar(50) NOT NULL COMMENT '账户',
>
> `password` char(32) NOT NULL COMMENT '密码',
>
> `name` varchar(50) NOT NULL COMMENT '姓名',
>
> `status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '状态 1开启 2关闭',
>
> `add\_time` int(10) unsigned NOT NULL COMMENT '添加时间',
>
> PRIMARY KEY (`uid`)
>
> ) ENGINE=MyISAM AUTO\_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='后台管理员';
* `connect`方法动态配置数据库连接信息
> Db::connect('ouyangke')->table('shop\_user')->select();
`connect`方法必须在查询的最开始调用,而且必须紧跟着调用查询方法,否则可能会导致部分查询失效或者依然使用默认的数据库连接
## 十三、WHRER 链式操作(不常用)
* 和查询表达式功能一样,ThinkPHP 提供以下快捷查询方法
连贯操作作用支持的参数类型whereOr*用于OR查询字符串、数组和对象whereLike*模糊查询字符串whereNotLike*模糊查询字符串whereBetween*区间查询字符串whereNotBetween*不在区间查询 字符串whereIn*IN查询字符串whereNotIn*不在IN查询字符串whereNull*查询字段是否是NULL字符串whereNotNull*查询字段是否不是NULL字符串whereExists*EXISTS查询字符串whereNotExists* 不在EXISTS查询字符串whereBetweenTime*时间区间比较字符串whereTime*用于时间日期的快捷查询字符串whereExp* 表达式查询,支持SQL语法字符串whereFindInSet*FIND_IN_SET查询字符串whereRaw*用于字符串条件直接查询和操作字符串
## 十四、其他链式操作(不常用)
连贯操作作用 支持的参数类型alias 用于给当前数据表定义别名 字符串strict 用于设置是否严格检测字段名是否存在 布尔值group 用于对查询的group支持字符串having 用于对查询的having支持字符串join*用于对查询的join支持字符串和数组union*用于对查询的union支持字符串、数组和对象distinct 用于查询的distinct支持布尔值lock 用于数据库的锁机制布尔值cache 用于查询缓存支持多个参数comment 用于SQL注释字符串force 用于数据集的强制索引字符串partition 用于设置分区信息数组 字符串failException 用于设置没有查询到数据是否抛出异常布尔值sequence 用于设置自增序列名字符串replace 用于设置使用REPLACE方式写入布尔值extra 用于设置额外查询规则字符串duplicate 用于设置DUPLCATE信息数组 字符串procedure 用于设置当前查询是否为存储过程查询布尔值master 用于设置主服务器读取数据布尔值view*用于视图查询 字符串、数组
## 十五、事务操作
* `InnoDB`引擎支持事务处理,`MyISAM`不支持事务处理
~~~
// 启动事务
Db::startTrans();
$data = ['cat'=>'1','title'=>'日系小浪漫与温暖羊毛针织拼接网纱百褶中长收腰连衣裙','price'=>'1598.35','add_time'=>1576080000];
$insert = Db::table('shop_goods')->insert($data);
if(empty($insert)){
// 回滚事务
Db::rollback();
}else{
// 提交事务
Db::commit();
}
~~~
* `transaction`方法操作数据库事务,当闭包中的代码发生异常会自动回滚
~~~
Db::transaction(function () {
$data = ['cat'=>'1','title'=>'日系小浪漫与温暖羊毛针织拼接网纱百褶中长收腰连衣裙','price'=>'1598.35','add_time'=>1576080000];
$insert = Db::table('shop_goods')->insert($data);
});
~~~
## 十六、数据集
* 数据库通过select查询,得到的数据集对象
* 返回的数据集对象是`think\Collection`,提供了和数组无差别用法,并且另外封装了一些额外的方法
编号方法描述1 isEmpty是否为空2 toArray 转换为数组3 all 所有数据4 merge 合并其它数据5 diff 比较数组,返回差集6 flip 交换数据中的键和值7 intersect 比较数组,返回交集8 keys 返回数据中的所有键名9 pop 删除数据中的最后一个元素10 shift 删除数据中的第一个元素11 unshift 在数据开头插入一个元素12 push 在结尾插入一个元素13 reduce 通过使用用户自定义函数,以字符串返回数组14 reverse 数据倒序重排15 chunk 数据分隔为多个数据块16 each 给数据的每个元素执行回调17 filter 用回调函数过滤数据中的元素18 column 返回数据中的指定列19sort对数据排序20 order 指定字段排序21 shuffle 将数据打乱22 slice 截取数据中的一部分23 map用回调函数处理数组中的元素24 where 根据字段条件过滤数组中的元素25 whereLikeLike查询过滤元素26 whereNotLike Not Like过滤元素27 whereIn IN查询过滤数组中的元素28 whereNotIn Not IN查询过滤数组中的元素29whereBetween Between查询过滤数组中的元素30whereNotBetweenNot Between查询过滤数组中的元素
~~~
$select = Db::table('shop_goods')
->field('title,price,id')
->where('status',1)
->order('price','DESC')
->select();
if($select->isEmpty()){
echo '未查询到数据';
}else{
print_r($select->toArray());
}
~~~
备:在模型中进行数据集查询,全部返回数据集对象,但使用的是`think\model\Collection类`(继承think\\Collection),但用法是一致的。