ThinkPHP6.0 数据库链式操作



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','<>','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">&#xe615;</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 当前页
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代码

<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,提供了和数组无差别用法,并且另外封装了一些额外的方法

编号方法描述
isEmpty是否为空
toArray 转换为数组
all 所有数据
merge 合并其它数据
diff 比较数组,返回差集
flip 交换数据中的键和值
intersect 比较数组,返回交集
keys 返回数据中的所有键名
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),但用法是一致的。