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 | 查询字段是否(不)是NULL | whereNull/whereNotNull |
where
查询
where方法在链式操作方法里面是最常用的方法,可以完成包括普通查询、表达式查询、快捷查询、区间查询、组合查询在内的条件查询操作
# 等于(=)
$select = Db::table('shop_goods')->where('id','=','1')->select();
print_r($select->toArray());
# 不等于(<>)
$select = Db::table('shop_goods')->where('id','<>','2')->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','<','5')->select();
print_r($select->toArray());
# 小于等于(<=)
$select = Db::table('shop_goods')->where('id','<=','6')->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代码
<form class="layui-form" method="post">
<div class="layui-form-item" style="margin-top:10px;">
<div class="layui-input-inline">
<select name="status">
<option value="0" {if $status==0}selected{/if}>全部</option>
<option value="1" {if $status==1}selected{/if}>开启</option>
<option value="2" {if $status==2}selected{/if}>关闭</option>
</select>
</div>
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i>搜索</button>
</div>
</form>
八、分页示例
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代码
<div class="layui-box layui-laypage layui-laypage-default">
<a href="/index.php/Index/index?p={$p-1}&status={$status}" class="layui-laypage-prev {if $p<=1}layui-disabled{/if}">上一页</a>
{for start="0" end="$count"}
{if $p == $i+1}
<span class="layui-laypage-curr">
<em class="layui-laypage-em"></em>
<em>{$i+1}</em>
</span>
{else/}
<a href="/index.php/Index/index?p={$i+1}&status={$status}">{$i+1}</a>
{/if}
{/for}
<a href="/index.php/Index/index?p={$p+1}&status={$status}" class="layui-laypage-next {if $p>=$count}layui-disabled{/if}">下一页</a>
</div>
九、模版分页
paginate
内置了分页实现,要给数据添加分页输出功能变得非常简单render
获取翻页html代码total
获取总数量
controller代码
$select = Db::table('shop_goods')->paginate(10);
print_r($select);echo '<hr>';
foreach($select as $v){
print_r($v);echo '<hr>';
}
print_r($select->render());echo '<hr>';
print_r('总数:'.$select->total());echo '<hr>';
View::assign([
'select' => $select
]);
return View::fetch();
view代码
<div>{$select|raw}</div>
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 | 当前页 |
path | url路径 |
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代码
<div>{$paginate|raw}</div>
十一、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 | 返回数据中的指定列 |
19 | sort | 对数据排序 |
20 | order | 指定字段排序 |
21 | shuffle | 将数据打乱 |
22 | slice | 截取数据中的一部分 |
23 | map | 用回调函数处理数组中的元素 |
24 | where | 根据字段条件过滤数组中的元素 |
25 | whereLike | Like查询过滤元素 |
26 | whereNotLike | Not Like过滤元素 |
27 | whereIn | IN查询过滤数组中的元素 |
28 | whereNotIn | Not IN查询过滤数组中的元素 |
29 | whereBetween | Between查询过滤数组中的元素 |
30 | whereNotBetween | Not 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),但用法是一致的。