如果想了解更多相关知识,可以前往我的个人博客看看:eyes++的个人空间

一:连接数据库与模型初探

ThinkPHP 采用内置抽象层将不同的数据库操作进行封装处理,数据抽象层基于 PDO 模式,无须针对不同的数据库编写相应的代码。使用数据库的第一步,就是连接数据库,在根目录的 config 下的 database.php 可以设置数据库连接信息,大部分系统已经给了默认值,你只需要修改和填写需要的值即可。
其中default配置用于设置默认使用的数据库连接配置。connections配置具体的数据库连接信息,default配置参数定义的连接配置必须要存在。

type 数据库
mysql MySQL
sqlite SqLite
pgsql PostgreSQL
sqlsrv SqlServer
mongo MongoDb
oracle Oracle

下面是默认支持的数据库连接信息:

参数名 描述 默认值
type 数据库类型
hostname 数据库地址 127.0.0.1
database 数据库名称
username 数据库用户名
password 数据库密码
hostport 数据库端口号
dsn 数据库连接dsn信息
params 数据库连接参数
charset 数据库编码 utf8
prefix 数据库的表前缀
deploy 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 0
rw_separate 数据库读写是否分离 主从式有效 false
master_num 读写分离后 主服务器数量 1
slave_no 指定从服务器序号
fields_strict 是否严格检查字段是否存在 true
fields_cache 是否开启字段缓存 false
schema_cache_path 字段缓存目录
trigger_sql 是否开启SQL监听 true
auto_timestamp 自动写入时间戳字段 false
query 指定查询对象 think\db\Query

我们还可以调用Db::connect方法动态配置数据库连接信息,例如:

\think\facade\Db::connect('demo')->table('user')->find();

connect方法必须在查询的最开始调用,而且必须紧跟着调用查询方法,否则可能会导致部分查询失效或者依然使用默认的数据库连接。且动态连接数据库的connect方法仅对当次查询有效。这种方式的动态连接和切换数据库比较方便,经常用于多数据库连接的应用需求。

对于本地测试,会优先采用.env 的配置信息,可以通过删除改变.env 的配置,或删除.env 来验证 database 的执行优先级,操作中我们和 database 配置对应上即可:

现在来测试有没有成功连接:

二:查询构造器(基础)

在学习查询之前可以先了解一下一个新方法:Db::getLastSql(),该方法可以返回最近一条SQL查询的原生语句。我在这里的演示是使用了我的myemployees库内容如下:

1) 查询数据

查询单个数据

查询单个数据一般使用find方法。如果没有任何的查询条件,并且也没有调用order方法的话 ,find查询不会返回任何结果。

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result = json(Db::table('employees')->where('employee_id', 100)->find());return Db::getLastSql() . '<br>' . $result;}
}

find方法查询结果不存在,返回 null,否则返回结果数组,如果希望查询数据不存在的时候返回空数组,可以如下修改:

$result = Db::table('employees')->where('employee_id', 99)->findOrEmpty();

如果希望在没有找到数据后抛出异常可以如下使用,如果没有查找到数据,则会抛出一个think\db\exception\DataNotFoundException异常。

$result = Db::table('employees')->where('employee_id', 99)->findOrFail();

查询数据集

查询多个数据(数据集)使用select方法:

select 方法查询结果是一个数据集对象,如果需要转换为数组可以如下使用,但一般DB操作返回是默认是数组,这种情况下调用toArray()会报错,别问我是怎么知道的。。。。

$result = Db::table('employees')->where('employee_id', 102)->select()->toArray();

如果希望在没有查找到数据后抛出异常可以如下使用,如果没有查找到数据,同样也会抛出一个think\db\exception\DataNotFoundException异常

$result = Db::table('employees')->where('employee_id', 102)->select()->selectOrFail();

如果设置了数据表前缀参数的话,可以使用name替代table,如果表名为"tp_user",然后在数据库设置那里添加了表前缀"tp_",那么查询时可以用name('user')替代table('tp_user')。如果你的数据表没有设置表前缀的话,那么name和table方法效果一致。

值和列查询

查询某个字段的值可以用value(),如果不存在则返回null,如果有多个结果则只返回第一个。
查询某一列的值可以用column(),第一个参数是返回的值,第二个参数的值作为索引。

数据分批处理

如果处理的数据量巨大,成百上千那种,一次性读取有可能会导致内存开销过大,为了避免内存处理太多数据出错,可以使用 chunk()方法分批处理数据,该方法一次获取结果集的一小块,然后填充每一小块数据到要处理的闭包,该方法在编写处理大量数据库记录的时候非常有用。比如,我们可以全部员工表数据进行分批处理,每次处理 3 个员工记录,先展示chunk分批次处理的特性。

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){// function传入的$data代表所有数据$result = Db::table('employees')->chunk(3, function ($data){foreach ($data as $data) {dump($data);}echo 1;});}
}

如果要给员工计算年薪,那就是 月薪*12*(1+奖金率),那样就可以通过如下方法计算了:

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){// function传入的$data代表所有数据$result = Db::table('employees')->chunk(3, function ($data){foreach ($data as $data) {if (isset($data['commission_pct'])) {echo $data['employee_id'] . ' ' . (12*$data['salary']*(1+$data['commission_pct'])) . "<br>";} else {echo $data['employee_id'] . ' ' . (12*$data['salary']) . "<br>";}}echo 1 . "<br>";});}
}

chunk方法的处理默认是根据主键查询,支持指定字段,并且支持指定处理数据的顺序。

Db::table('think_user')->chunk(100, function($users) {// 处理结果集...return false;
},'create_time', 'desc');

游标查询

可以利用游标查询功能,可以大幅度减少海量数据的内存开销,它利用了 PHP 生 成器特性。每次查询只读一行,然后再读取时,自动定位到下一行继续读取,cursor方法返回的是一个生成器对象。

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result = Db::table('employees')->cursor();foreach ($result as $e){echo $e['last_name'] . "<br>";};}
}

2) 添加数据

单数据新增

单数据新增一般使用insert()方法插入,如果新增成功会返回一个1,没有指定的列的值默认为null。

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$data = ['employee_id'   =>  '99','first_name'    =>  'eyes','last_name'     =>  '++'];return Db::table('employees')->insert($data);}
}

如果你添加一个不存在的字段数据,会抛出一个异常 Exception,如果想强行新增抛弃不存在的字段数据,则使用 strick(false)方法,忽略异常:

return Db::table('employees')->strict(false)->insert($data);

我采用的数据库是 mysql,可以支持 replace 写入,insert 和 replace 写入的区别,前者遇到表中存在主键相同则报错,后者则修改。另外,使用 insertGetId()方法,可以在新增成功后返回当前数据 ID

批量数据新增

使用 insertAll()方法,可以添加二维数组批量新增数据,但要保持数组结构一致,成功则返回增加的行数

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$data =[['employee_id'   =>  '98','first_name'    =>  '虚哥','last_name'     =>  'xx'],['employee_id'   =>  '97','first_name'    =>  '鸡哥','last_name'     =>  'jj']];return Db::table('employees')->insertAll($data);}
}


如果是mysql数据库则可以使用replay()批量添加或修改:

return Db::table('employees')->replay()->insertAll($data);

如果批量插入的数据比较多,可以指定分批插入,使用limit方法指定每次插入的数量限制:

//分批次写入,每次最多100条数据
Db::table('employees')->replay()->limit(100)->insertAll($data);

save()新增

save()方法是一个通用方法,可以自行判断是新增还是修改(更新)数据,判断的依据是是否存在主键,不存在即新增。用法如insert,此处略。

3) 更新数据

更新数据可以使用save()方法或者update()方法,如果修改数据包括了主键信息,则可以省略where条件

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$data =['first_name'    =>  '东哥','last_name'     =>  'hh'];return Db::table('employees')->where('employee_id', 97)->save($data);
//        支持使用data方法传入要更新的数据,如果update方法和data方法同时传入更新数据,则以update方法为准。
//        return Db::table('employees')
//        ->where('employee_id', 97)
//        ->data($data)
//        ->save();}
}

如果要更新的数据需要使用SQL函数或者其它字段,可以使用下面的方式:

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){return Db::table('employees')->where('employee_id', 99)->exp('first_name', 'UPPER(first_name)')->update();}
}


可以使用inc/dec方法自增或自减一个字段的值( 如不加第二个参数,默认步长为1)。

// score 字段加 1
Db::table('employees')->where('employee_id', 1)->inc('salary')->update();// score 字段加 5
Db::table('employees')->where('employee_id', 1)->inc('salary', 5)->update();// score 字段减 1
Db::table('employees')->where('employee_id', 1)->dec('salary')->update();// score 字段减 5
Db::table('employees')->where('employee_id', 1)->dec('salary', 5)->update();

4) 删除数据

  • 极简删除可以根据主键直接删除,删除成功返回影响行数,否则 0;
    Db::table('employees')->delete(100);
  • 根据主键,还可以删除多条记录;
    Db::table('employees')->delete([97,98,99]);
  • 正常情况下,通过 where()方法来删除;
    Db::table('employees')->where('id', 100)->delete();
  • 通过 true 参数删除数据表所有数据
    Db::table('employees')->delete(true);

一般情况下,业务数据不建议真实删除数据,系统提供了软删除机制(模型中使用软删除更为方便),useSoftDelete方法表示使用软删除,并且指定软删除字段为delete_time,写入数据为当前的时间戳。。

// 软删除数据 使用delete_time字段标记删除
Db::table('employees')->where('id', 100)->useSoftDelete('delete_time',time())->delete();

5) 查询表达式

查询表达式支持大部分的SQL查询语法,也是ThinkPHP查询语言的精髓,查询表达式的使用格式:where('字段名','查询表达式','查询条件')。除了where方法外,还可以支持whereOr,用法是一样的。为了更加方便查询,大多数的查询表达式都提供了快捷查询方法。

表达式 含义 快捷查询方法
= 等于
<> 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于
[NOT] LIKE 模糊查询 whereLike/whereNotLike
[NOT] BETWEEN (不在)区间查询 whereBetween/whereNotBetween
[NOT] IN (不在)IN 查询 whereIn/whereNotIn
[NOT] NULL 查询字段是否(不)是NULL whereNull/whereNotNull
[NOT] EXISTS EXISTS查询 whereExists/whereNotExists
[NOT] REGEXP 正则(不)匹配查询(仅支持Mysql)
[NOT] BETWEEN TIME 时间区间比较 whereBetweenTime
> TIME 大于某个时间 whereTime
< TIME 小于某个时间 whereTime
>= TIME 大于等于某个时间 whereTime
<= TIME 小于等于某个时间 whereTime
EXP 表达式查询,支持SQL语法 whereExp
find in set FIND_IN_SET查询 whereFindInSet

比较查询

  • 查询表达式支持大部分常用的 SQL 语句,语法格式如下:
    where('字段名','查询表达式','查询条件');
  • 在查询数据进行筛选时,我们采用 where()方法,比如 id=80;
    Db::name('user')->where('id', 80)->find();
    Db::name('user')->where('id','=',80)->find();
  • 使用<>、>、<、>=、<=可以筛选出各种符合比较值的数据列表; Db::name('user')->where('id','>',80)->select();

区间查询

  • 使用 like 表达式进行模糊查询;
    Db::name('user')->where('email','like','xiao%')->select();
  • like 表达式还可以支持数组传递进行模糊查询;
    Db::name('user')->where('email','like',['xiao%','wu%'], 'or')->select();
    SELECT * FROM tp_user WHERE (email LIKE xiao% OR email LIKE 'wu%')
  • like 表达式具有两个快捷方式 whereLike()和 whereNoLike(); Db::name('user')->whereLike('email','xiao%')->select();
    Db::name('user')->whereNotLike('email','xiao%')->select();
  • between 表达式具有两个快捷方式 whereBetween()和 whereNotBetween(); Db::name('user')->where('id','between','19,25')->select();
    Db::name('user')->where('id','between',[19, 25])->select();
    Db::name('user')->whereBetween('id','19,25')->select(); Db::name('user')->whereNotBetween('id','19,25')->select();
  • in 表达式具有两个快捷方式 whereIn()和 whereNotIn();
    Db::name('user')->where('id','in', '19,21,29')->select();
    Db::name('user')->where('id','in', [19, 21, 29])->select();
    Db::name('user')->whereIn('id','19,21,29')->select();
    Db::name('user')->whereNotIn('id','19,21,29')->select();
  • null 表达式具有两个快捷方式 whereNull()和 whereNotNull(); Db::name('user')->where('uid','null')->select();
    Db::name('user')->where('uid','not null')->select();
    Db::name('user')->whereNull('uid')->select();
    Db::name('user')->whereNotNull('uid')->select();

EXP查询

EXP表达式支持更复杂的查询:

Db::name('user')->where('id','in','1,3,8')->select();

可以改成:

Db::name('user')->where('id','exp',' IN (1,3,8) ')->select();

exp查询的条件不会被当成字符串,所以后面的查询条件可以使用任何SQL支持的语法,包括使用函数和字段名称。因此推荐使用whereExp方法查询。

Db::name('user')->whereExp('id', 'IN (1,3,8) ')->select();

三:查询构造器(链式)

1).查询规则

  1. 前面课程中我们通过指向符号“->”多次连续调用方法称为:链式查询
  2. 当 Db::name(‘user’)时,返回查询对象(Query),即可连缀数据库对应的方法
  3. 而每次执行一个数据库查询方法时,比如 where(),还将返回查询对象(Query)
  4. 只要还是数据库对象,那么就可以一直使用指向符号进行链式查询
  5. 再利用 find()、select()等方法返回数组(Array)或数据集对象(Colletion)
  6. 而 find()和 select()是结果查询方法(放在最后),并不是链式查询方法
    Db::name('user')->where('id', 27)->order('id', 'desc')->find()
  7. 除了查询方法可以使用链式连贯操作,CURD 操作也可以使用(后续课程研究)

2).更多查询

  1. 如果多次使用数据库查询,那么每次静态创建都会生成一个实例,造成浪费;
  2. 我们可以把对象实例保存下来,再进行反复调用即可;
    $userQuery = Db::name('user');
    $dataFind = $userQuery->where('id', 27)->find();
    $dataSelect = $userQuery->select();
  3. 当同一个对象实例第二次查询后,会保留第一次查询的值;
    $data1 = $userQuery->order('id', 'desc')->select();
    $data2 = $userQuery->select();
    return Db::getLastSql();
    SELECT * FROM tp_user ORDER BY id DESC
  4. 使用 removeOption()方法,可以清理掉上一次查询保留的值; $userQuery->removeOption('where')->select();

3). 链式查询方法

where

  • 表达式查询,即where()方法的基础查询方式
 $result=Db::table('employees')->where('salary', '<', '10000')->select();
  • 关联数组查询,通过键值对来数组键值对匹配的查询方式
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where(['job_id'     =>      'IT_PROG','salary'     =>       6000])->select();return json($result);}
}

  • 索引数组查询,通过数组里的数组拼装方式来查询
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where([['employee_id', '<', 110],['salary', '<', 10000]])->select();return json($result);}
}

  • 将复杂的数组组装后,通过变量传递,将增加可读性
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$map[] = ['employee_id', '<', 110];$map[] = ['salary', 'in', [6000, 4200, 24000]];$result=Db::table('employees')->where($map)->select();return json($result);}
}

  • 字符串形式传递,简单粗暴的查询方式,whereRaw()支持复杂字符串格式,也支持SQL预处理模式
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->whereRaw("employee_id<110 AND salary IN (24000, 6000, 4200)")->select();return json($result);}
}

field

  • 使用 field()方法,可以指定要查询的字段
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where('employee_id', '<', 105)->field('employee_id, first_name, salary')
//                  ->field(['employee_id', 'first_name', 'salary']) 或者这种数组形式->select();return json($result);}
}

  • 使用 field()方法,给指定的字段设置别名
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where('employee_id', '<', 105)->field('employee_id as id, first_name as name, salary as 薪水')->select();return json($result);}
}

  • 在 fieldRaw()方法里,可以直接给字段设置 MySQL 函数
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where('employee_id', '<', 105)->field('job_id, LENGTH(job_id)')->select();return json($result);}
}

  • 使用 field(true)的布尔参数,可以显式的查询获取所有字段,而不是*
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where('employee_id', '<', 105)->field(true)->select();return json($result);}
}

  • 使用 withoutField()方法中字段排除,可以屏蔽掉想要不显示的字段
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where('employee_id', '<', 105)->withoutField('email, phone_number')->select();return json($result);}
}

  • 使用 field()方法在新增时,验证字段的合法性
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->where('employee_id', '<', 105)->field('employee_id, first_name, last_name')->insert(['first_name'       =>      '济钢','last_name'        =>       'aa']);return json($result);}
}

alias

使用 alias()方法,给数据库起一个别名:

limit

  • 使用 limit()方法,限制获取输出数据的个数
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('employee_id, last_name')->limit(5)->select();return json($result);}
}

  • 分页模式,即传递两个参数,比如从第 3 条开始显示 5 条 limit(2,5)
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('employee_id, last_name')->limit(2, 5)->select();return json($result);}
}

page

page()分页方法,优化了 limit()方法,无须计算分页条数

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('employee_id, last_name')->page(2, 5)  // 每页显示五条,第二页->select();return json($result);}
}

order

  • 使用 order()方法,可以指定排序方式,没有指定第二参数,默认 asc
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('employee_id, last_name, salary')->order('salary', 'desc')->select();return json($result);}
}

  • 支持数组的方式,对多个字段进行排序
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('employee_id, last_name, salary')// 按工资升序,工资相同则按员工编号降序->order(['salary'        =>       'asc','employee_id'   =>       'desc'])->select();return json($result);}
}

  • 使用 orderRaw()方法,支持排序的时候指定 MySQL 函数
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('employee_id, last_name, salary')->orderRaw('length(first_name) DESC')->select();return Db::getLastSQL();}
}

group

  • 使用 group()方法,给性别不同的人进行 price 字段的总和统计
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('job_id, SUM(salary)')->group('job_id')->select();return json($result);}
}

  • 也可以进行多字段分组统计
<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('job_id, manager_id, SUM(salary)')->group('job_id, manager_id')->select();return json($result);}
}

having

使用 group()分组之后,再使用 having()进行筛选

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$result=Db::table('employees')->field('job_id, manager_id, SUM(salary)')->group('job_id, manager_id')->having('SUM(salary)>10000')->select();return json($result);}
}

四:查询构造器(进阶)

1) 聚合查询

在应用中我们经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数、所有用户的最大积分、用户的平均成绩等等,ThinkPHP为这些统计操作提供了一系列的内置方法,包括以下部分:

方法 说明
count 统计数量,参数是要统计的字段名(可选)
max 获取最大值,参数是要统计的字段名(必须)
min 获取最小值,参数是要统计的字段名(必须)
avg 获取平均值,参数是要统计的字段名(必须)
sum 获取总分,参数是要统计的字段名(必须)
  1. 使用 count()方法,可以求出所查询数据的数量
    Db::name('user')->count();
  2. count()可设置指定 id,比如有空值(Null)的 uid,不会计算数量;
    Db::name('user')->count('uid');
  3. 使用 max()方法,求出所查询数据字段的最大值;
    Db::name('user')->max('price');
  4. 如果 max()方法,求出的值不是数值,则通过第二参数强制转换;
    Db::name('user')->max('price', false);
  5. 使用 min()方法,求出所查询数据字段的最小值,也可以强制转换;
    Db::name('user')->min('price');
  6. 使用 avg()方法,求出所查询数据字段的平均值;
    Db::name('user')->avg('price');
  7. 使用 sum()方法,求出所查询数据字段的总和;
    Db::name('user')->sum('price');

2) 分页查询

3) 时间查询

传统方式

  • 可以使用>、<、>=、<=来筛选匹配时间的数据;
    Db::name('user')->where('create_time', '>', '2018-1-1')->select();
  • 可以使用 between 关键字来设置时间的区间
    Db::name('user')->where('create_time', 'between', ['2018-1-1', '2019-12-31'])->select();
    Db::name('user')->where('create_time', 'not between', ['2018-1-1', '2019-12-31'])->select();

快捷方式

  • 时间查询的快捷方法为 whereTime(),直接使用>、<、>=、<=; Db::name('user')->whereTime('create_time', '>', '2018-1-1')->select();
  • 快捷方式也可以使用 between 和 not between;
    Db::name('user')->whereBetween('create_time', ['2018-1-1', '2019-12-31'])->select();
  • 还有一种快捷方式为:whereBetweenTime()和 whereNotBetweenTime(); Db::name('user')->whereBetweenTime('create_time', '2018-1-1', '2019-12-31')->select();
  • 默认的大于>,可以省略;
    Db::name('user')->whereTime('create_time', '2018-1-1')->select();

固定查询

  • 使用 whereYear 查询今年的数据、去年的数据和某一年的数据
    Db::name('user')->whereYear('create_time')->select();
    Db::name('user')->whereYear('create_time', 'last year')->select();
    Db::name('user')->whereYear('create_time', '2016')->select();
  • 使用 whereMonth 查询当月的数据、上月的数据和某一个月的数据
    Db::name('user')->whereMonth('create_time')->select();
    Db::name('user')->whereMonth('create_time', 'last month')->select();
    Db::name('user')->whereMonth('create_time', '2016-6')->select();
  • 使用 whereDay 查询今天的数据、昨天的数据和某一个天的数据
    Db::name('user')->whereDay('create_time')->select();
    Db::name('user')->whereDay('create_time', 'last day')->select();
    Db::name('user')->whereDay('create_time', '2016-6-27')->select();

其它查询

  • 查询指定时间的数据,比如两小时内的
    Db::name('user')->whereTime('create_time', '-2 hours')->select();
  • 查询两个时间字段时间有效期的数据,比如会员开始到结束的期间
    Db::name('user')->whereBetweenTimeField('start_time', 'end_time')->select();

4) 高级查询

快捷查询

快捷查询方式是一种多字段相同查询条件的简化写法,可以进一步简化查询条件的写法,在多个字段之间用|分割表示OR查询,用&分割表示AND查询,可以实现下面的查询,例如:

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){Db::table('employees')->where('first_name|last_name', 'like', '%a%')->where('employee_id&manager_id', '>', 103)->select();return Db::getLastSql();}
}

闭包查询

<?php
namespace app\controller;
use think\facade\Db;class DbTest
{public function index(){$jobId='IT_PROG';$salary=11000;$res=Db::table('employees')->where(function ($query) use($jobId, $salary) {$query->where('job_id', $jobId)->whereOr('salary', '>', $salary);})->select();return json($res);}
}

字符串条件查询

对于一些实在复杂的查询,也可以直接使用原生SQL语句进行查询,例如:

Db::table('think_user')->whereRaw('id > 0 AND name LIKE "thinkphp%"')->select();

为了安全起见,我们可以对字符串查询条件使用参数绑定,例如:

Db::table('think_user')->whereRaw('id > :id AND name LIKE :name ', ['id' => 0, 'name' => 'thinkphp%'])->select();

快捷方法

系统封装了一系列快捷方法,用于简化查询

方法 作用
whereOr 字段OR查询
whereXor 字段XOR查询
whereNull 查询字段是否为Null
whereNotNull 查询字段是否不为Null
whereIn 字段IN查询
whereNotIn 字段NOT IN查询
whereBetween 字段BETWEEN查询
whereNotBetween 字段NOT BETWEEN查询
whereLike 字段LIKE查询
whereNotLike 字段NOT LIKE查询
whereExists EXISTS条件查询
whereNotExists NOT EXISTS条件查询
whereExp 表达式查询
whereColumn 比较两个字段

动态查询

查询构造器还提供了动态查询机制,用于简化查询条件

动态查询 描述
whereFieldName 查询某个字段的值
whereOrFieldName 查询某个字段的值
getByFieldName 根据某个字段查询
getFieldByFieldName 根据某个字段获取某个值
// 根据邮箱(email)查询用户信息
$user = Db::table('user')->whereEmail('thinkphp@qq.com')->find();// 根据昵称(nick_name)查询用户
$email = Db::table('user')->whereNickName('like', '%流年%')->select();// 根据邮箱查询用户信息
$user = Db::table('user')->getByEmail('thinkphp@qq.com');// 根据昵称(nick_name)查询用户信息
$user = Db::table('user')->field('id,name,nick_name,email')->getByNickName('流年');// 根据邮箱查询用户的昵称
$nickname = Db::table('user')->getFieldByEmail('thinkphp@qq.com', 'nick_name');// 根据昵称(nick_name)查询用户邮箱
$email = Db::table('user')->getFieldByNickName('流年', 'email');

5) 子查询

使用 fetchSql()方法,可以设置不执行 SQL,而返回 SQL 语句,默认 true;
Db::name('user')->fetchSql(true)->select();
使用 buildSql()方法,也是返回 SQL 语句,不需要再执行 select(),且有括号
Db::name('user')->buildSql(true);
结合以上方法,我们实现一个子查询:

$subQuery = Db::table('think_user')->field('id,name')->where('id', '>', 10)->buildSql();
Db::table($subQuery . ' a')->where('a.name', 'like', 'thinkphp')->order('id', 'desc')->select();

子查询还有闭包模式,IN/NOT INEXISTS/NOT EXISTS之类的查询可以直接使用闭包作为子查询,例如:

Db::table('think_user')->where('id', 'IN', function ($query) {$query->table('think_profile')->where('status', 1)->field('id');})->select();

6) 原生查询

注意:V6.0.3+版本开始,原生查询仅支持Db类操作,不支持在模型中调用原生查询方法(包括query和execute方法)。
Db类支持原生SQL查询操作,主要包括query方法和execute方法

query方法用于执行SQL查询操作,返回查询结果数据集(数组)。

Db::query("select * from think_user where status=:id", ['id' => 1]);

execute用于更新和写入数据的sql操作,如果数据非法或者查询错误则返回false,否则返回影响的记录数。

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]);

thinkphp的数据库操作(上)相关推荐

  1. ThinkPHP6之数据库操作上

    ThinkPHP6之数据库操作上 前言 1. 数据库配置 2. 数据库操作 1. 查询操作 2. 插入操作 3. 修改 4. 删除 5. 其他 3.数据集 总结 前言 注意,tp6在进行语法学习的时候 ...

  2. Node.js SQL数据库操作 (上)(操作MySQL数据库及 数据库连接池)

    文章目录 Node.js MySQL驱动 操作 MySQL 数据库 连接 MySQL 数据库 增删改查操作 防止 SQL 注入攻击 数据库连接池操作 Node.js MySQL驱动 Node.js的原 ...

  3. thinkphp 5数据库操作

    1.原生sql $options=Db::table('__MALL_POST__') ->alias('m') ->join('__MALL_CATEGORY_VALUE__ v','m ...

  4. 使用Memcache缓存mysql数据库操作的原理和缓存过程浅析

    1.首先明确是不是一定要上缓存,当前架构的瓶颈在哪里,若瓶颈真是数据库操作上,再继续往下看. 2.明确memcached和redis的区别,到底要使用哪个.前者终究是个缓存,不可能永久保存数据(LRU ...

  5. thinkphp mysql操作数据库_thinkPHP数据库操作

    thinkPHP如果要对数据库操作,一般来说首先要做的是在配置文件中链接数据库,然后用M方法实例化一张表,然后就是对表的操作了 可以开启调试功能查看程序执行的sql语句: 1.开启调试功能(默认是已经 ...

  6. ThinkPHP(7)——数据库操作

    连接数据库 实例化模型 实例化基础模型 实例化自定义模型 实例化空模型 增删改查 add select update delete order排序 field字段选择 limit page分页 gro ...

  7. ThinkPHP自动化为已经上传的图片添加「 响应式」水印(数据库字段部分)

    版权属于: Postbird - There I am , in the world more exciting! 原文地址: http://www.ptbird.cn/thinkphp-image- ...

  8. .ne中的控制器循环出来的数据如何显示在视图上_Web程序设计-ASP.NET MVC4数据库操作实例...

    ASP.NET MVC4数据库操作实例 之前文章介绍了MVC4与Pure框架结合进行的网页设计过程中如何定义控制器.方法.模型.视图等.并使用实例进行了简单说明.本文将在此基础上进一步说明如何使用MV ...

  9. php读取excel中数据库,ThinkPHP 框架实现的读取excel导入数据库操作示例

    本文实例讲述了ThinkPHP 框架实现的读取excel导入数据库操作.分享给大家供大家参考,具体如下: 入口文件中: require_once VENDOR_PATH.'PHPExcel/PHPEx ...

最新文章

  1. java时间操作方法Calendar
  2. linux操作小技巧
  3. 二维树状数组 BZOJ 1452 [JSOI2009]Count
  4. Fixed: MacOS Mojave(10.14) 解决终端用Crontab报权限问题(不管是Root还是普通用户)及Linux基础(shell)...
  5. 10.14.2 快捷键,环境变量等
  6. Elastic-Job配置步骤
  7. Jest + React Testing Library 单测总结
  8. java常用类介绍及源码阅读(LinkedList)
  9. 信号量进程同步与互斥
  10. jQuery中的ajax、jquery中ajax全局事件、load实现页面无刷新局部加载、ajax跨域请求jsonp、利用formData对象向服务端异步发送二进制数据,表单序列化(异步获取表单内容)
  11. python箴言_Python高效率编程的8条箴言
  12. Android UI库书签
  13. thinkphp6 redis并发解决处理方案
  14. 百度正用谷歌AlphaGo,解决一个比围棋更难的问题 | 300块GPU在燃烧
  15. python 搭建的http 动态服务器_Python3搭建http服务器的实现代码
  16. Asp.Net母版页元素ID不一致的体现
  17. table中background背景图片自动拉伸
  18. vfp 中调用硬盘_硬盘你真的选对了么?固态真的好用么?细数硬盘这些年出现的坑!...
  19. Ubuntu 18.04安装Apollo 6.0:从零开始到启动Demo(超多细节)
  20. 什么是CMPP、SGIP、SMGP三大运营商接口协议

热门文章

  1. java查询历史记录的思路_JavaWeb之商品查看后历史记录代码实现
  2. width:100vh有感而发
  3. 无限火力更新服务器公告,英雄联盟无限火力官网公告2021?无限火力怎么玩?...
  4. ucore操作系统总结
  5. BitTorrent一种内容分发协议
  6. spring集成quartz报org.springframework.scheduling.quartz.CronTriggerBean异常
  7. Python字符串转16进制数字
  8. 微信小程序的经验总结,UI组件、图表、自定义bar你学会了吗
  9. 博恩.崔西七步成功公式
  10. 微信小程序动态的显示或隐藏控件