数据库

连接数据库

一、配置文件

database.php文件配置

return [
    // 数据库类型
    'type'        => 'mysql',
    // 服务器地址
    'hostname'    => '127.0.0.1',
    // 数据库名
    'database'    => 'thinkphp',
    // 数据库用户名
    'username'    => 'root',
    // 数据库密码
    'password'    => '',
    // 数据库连接端口
    'hostport'    => '',
    // 数据库连接参数
    'params'      => [],
    // 数据库编码默认采用utf8
    'charset'     => 'utf8',
    // 数据库表前缀
    'prefix'      => 'think_',
];

 二、方法配置

Db::connect([
    // 数据库类型
    'type'        => 'mysql',
    // 数据库连接DSN配置
    'dsn'         => '',
    // 服务器地址
    'hostname'    => '127.0.0.1',
    // 数据库名
    'database'    => 'thinkphp',
    // 数据库用户名
    'username'    => 'root',
    // 数据库密码
    'password'    => '',
    // 数据库连接端口
    'hostport'    => '',
    // 数据库连接参数
    'params'      => [],
    // 数据库编码默认采用utf8
    'charset'     => 'utf8',
    // 数据库表前缀
    'prefix'      => 'think_',
])->table('user')->find();

//字符串连接
Db::connect('mysql://root:1234@127.0.0.1:3306/thinkphp#utf8')
	->table('user')
    ->find();

connect方法必须在查询的最开始调用,而且必须紧跟着调用查询方法,否则可能会导致部分查询失效或者依然使用默认的数据库连接。

字符串连接的定义格式为:

数据库类型://用户名:密码@数据库地址:数据库端口/数据库名#字符集

字符串方式可能无法定义某些参数,例如前缀和连接参数。

实际应用中,我们应当尽量避免把数据库配置信息写在代码中,而应该统一定义在配置文件,我们可以在数据库配置文件中增加额外的配置参数,例如:

return [
    // 数据库类型
    'type'        => 'mysql',
    // 服务器地址
    'hostname'    => '127.0.0.1',
    // 数据库名
    'database'    => 'thinkphp',
    // 数据库用户名
    'username'    => 'root',
    // 数据库密码
    'password'    => '',
    // 数据库连接端口
    'hostport'    => '',
    // 数据库连接参数
    'params'      => [],
    // 数据库编码默认采用utf8
    'charset'     => 'utf8',
    // 数据库表前缀
    'prefix'      => 'think_',
    //数据库配置1
    'db_config1' => [
        // 数据库类型
        'type'        => 'mysql',
        // 服务器地址
        'hostname'    => '192.168.1.8',
        // 数据库名
        'database'    => 'thinkphp',
        // 数据库用户名
        'username'    => 'root',
        // 数据库密码
        'password'    => '1234',
        // 数据库编码默认采用utf8
        'charset'     => 'utf8',
        // 数据库表前缀
        'prefix'      => 'think_',
    ],
    //数据库配置2
    'db_config2' => 'mysql://root:1234@192.168.1.10:3306/thinkphp#utf8',
];

然后需要动态链接的时候使用下面的方式

Db::connect('db_config1')->table('user')->find();
Db::connect('db_config2')->table('user')->find();

动态连接数据库的connect方法仅对当次查询有效。

这种方式的动态连接和切换数据库比较方便,经常用于多数据库连接的应用需求。

三、模型类定义

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    // 直接使用配置参数名
    protected $connection = 'db_config1';
}

需要注意的是,ThinkPHP的数据库连接是惰性的,所以并不是在实例化的时候就连接数据库,而是在有实际的数据操作的时候才会去连接数据库。

查询构造器

一、查询数据

i 基本查询

1. 单个数据查询

(1)find()

// table方法必须指定完整的数据表名
Db::table('think_user')->where('id',1)->find();

find 方法查询结果不存在,返回 null,否则返回结果数组 

(2)findOrFail()

// table方法必须指定完整的数据表名
Db::table('think_user')->where('id',1)->findOrFail();

如果没有查找到数据,则会抛出一个think\db\exception\DataNotFoundException异常。

(3)findOrEmpty()

// table方法必须指定完整的数据表名
Db::table('think_user')->where('id',1)->findOrEmpty();

V5.1.23+版本开始,支持findOrEmpty方法,当查询不存在的时候返回空数组而不是Null。

2. 查询多个数据(数据集)

(1)select()

Db::table('think_user')->where('status',1)->select();

select 方法查询结果是一个二维数组,如果结果不存在,返回空数组

(2) selectOrFail()

Db::table('think_user')->where('status',1)->selectOrFail();

如果没有查找到数据,同样也会抛出一个think\db\exception\DataNotFoundException异常。

 注:

如果你的数据表没有设置表前缀的话,那么nametable方法效果一致。

findselect方法之前可以使用所有的链式操作(参考链式操作章节)方法。默认情况下,findselect方法返回的都是数组,区别在于后者是二维数组。

3. 助手函数

系统提供了一个db助手函数,可以更方便的查询:

db('user')->where('id',1)->find();
db('user')->where('status',1)->select();

db方法的第一个参数的作用和name方法一样,如果需要使用不同的数据库连接,可以使用:

db('user','db_config1')->where('id', 1)->find();

ii 值和列查询

1. 查询某个字段的值

// 返回某个字段的值
Db::table('think_user')->where('id',1)->value('name');

value 方法查询结果不存在,返回 null

2. 查询某一列的

// 返回数组
Db::table('think_user')->where('status',1)->column('name');
// 指定id字段的值作为索引
Db::table('think_user')->where('status',1)->column('name','id');

如果要返回完整数据,并且添加一个索引值的话,可以使用

// 指定id字段的值作为索引 返回所有数据
Db::table('think_user')->where('status',1)->column('*','id');

column 方法查询结果不存在,返回空数组

iii 数据分批处理

用户表数据进行分批处理,每次处理 100 个用户记录:

Db::table('think_user')->chunk(100, function($users) {
    foreach ($users as $user) {
        //
    }
});
// 或者交给回调方法myUserIterator处理
Db::table('think_user')->chunk(100, 'myUserIterator');

你可以通过从闭包函数中返回false来中止对后续数据集的处理:

Db::table('think_user')->chunk(100, function($users) {
    foreach ($users as $user) {
        // 处理结果集...
		if($user->status==0){
            return false;
        }
    }
});

也支持在chunk方法之前调用其它的查询方法,例如:

Db::table('think_user')
->where('score','>',80)
->chunk(100, function($users) {
    foreach ($users as $user) {
        //
    }
});

chunk方法的处理默认是根据主键查询,支持指定字段,例如:

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

并且支持指定处理数据的顺序。

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

chunk方法一般用于命令行操作批处理数据库的数据,不适合WEB访问处理大量数据,很容易导致超时。

iiii 大批量数据处理

新版提供的游标查询功能

$cursor = Db::table('user')->where('status', 1)->cursor();
foreach($cursor as $user){
	echo $user['name'];
}

cursor方法返回的是一个生成器对象,user变量是数据表的一条数据(数组)。

iv JSON类型数据查询(mysql

// 查询JSON类型字段 (info字段为json类型)
Db::table('think_user')
	->where('info->email','thinkphp@qq.com')
	->find();

二、添加数据

1. 添加一条数据

使用 Db 类的 insert 方法向数据库提交数据

$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::name('user')->insert($data);

insert 方法添加数据成功返回添加成功的条数,通常情况返回 1

或者使用data方法配合insert使用。

$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::name('user')
    ->data($data)
    ->insert();

如果你的数据表里面没有foo或者bar字段,那么就会抛出异常。

如果不希望抛出异常,可以使用下面的方法:

$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::name('user')->strict(false)->insert($data);

不存在的字段的值将会直接抛弃。

如果是mysql数据库,支持replace写入(若存在则更新,若不存在则插入),例如:

$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::name('user')->insert($data, true);

添加数据后如果需要返回新增数据的自增主键,可以使用insertGetId方法新增数据并返回主键值:

$userId = Db::name('user')->insertGetId($data);

 2. 添加多条数据

添加多条数据直接向 Db 类的 insertAll 方法传入需要添加的数据即可

$data = [
    ['foo' => 'bar', 'bar' => 'foo'],
    ['foo' => 'bar1', 'bar' => 'foo1'],
    ['foo' => 'bar2', 'bar' => 'foo2']
];
Db::name('user')->insertAll($data);

insertAll 方法添加数据成功返回添加成功的条数

如果是mysql数据库,支持replace写入,例如:

$data = [
    ['foo' => 'bar', 'bar' => 'foo'],
    ['foo' => 'bar1', 'bar' => 'foo1'],
    ['foo' => 'bar2', 'bar' => 'foo2']
];
Db::name('user')->insertAll($data, true);

也可以使用data方法

$data = [
    ['foo' => 'bar', 'bar' => 'foo'],
    ['foo' => 'bar1', 'bar' => 'foo1'],
    ['foo' => 'bar2', 'bar' => 'foo2']
];
Db::name('user')->data($data)->insertAll();

确保要批量添加的数据字段是一致的

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

$data = [
    ['foo' => 'bar', 'bar' => 'foo'],
    ['foo' => 'bar1', 'bar' => 'foo1'],
    ['foo' => 'bar2', 'bar' => 'foo2']
    ...
];
// 分批写入 每次最多100条数据
Db::name('user')->data($data)->limit(100)->insertAll();

三、更新数据

1. 更新数据

Db::name('user')
    ->where('id', 1)
    ->update(['name' => 'thinkphp']);

update 方法返回影响数据的条数,没修改任何数据返回 0

支持使用data方法传入要更新的数据

Db::name('user')
    ->where('id', 1)
    ->data(['name' => 'thinkphp'])
    ->update();

如果数据中包含主键,可以直接使用:

Db::name('user')
    ->update(['name' => 'thinkphp','id'=>1]);

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

Db::name('user')
    ->where('id',1)
    ->inc('read_time')
    ->dec('score',3)
    ->exp('name','UPPER(name)')
    ->update();

V5.1.7+版本以后,支持使用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')
    ]);

2. 更新字段值

(1)setField ()

Db::name('user')
    ->where('id',1)
    ->setField('name', 'thinkphp');

 

setField 方法返回影响数据的条数,没修改任何数据字段返回 0

(2)setInc/setDec方法自增或自减一个字段的值( 如不加第二个参数,默认步长为1)

// score 字段加 1
Db::table('think_user')
    ->where('id', 1)
    ->setInc('score');
// score 字段加 5
Db::table('think_user')
    ->where('id', 1)
    ->setInc('score', 5);
// score 字段减 1
Db::table('think_user')
    ->where('id', 1)
    ->setDec('score');
// score 字段减 5
Db::table('think_user')
    ->where('id', 1)
    ->setDec('score', 5);

setInc/setDec支持延时更新,如果需要延时更新则传入第三个参数,下例中延时10秒更新。

Db::name('user')->where('id', 1)->setInc('score', 1, 10);

setInc/setDec 方法返回影响数据的条数,如果使用了延迟更新的话,可能会返回true

四、删除数据

// 根据主键删除
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 方法返回影响数据的条数,没有删除返回 0

如果不带任何条件调用delete方法会提示错误,如果你确实需要删除所有数据,可以使用

// 无条件删除所有数据
Db::name('user')->delete(true);

五、查询表达式

查询表达式支持大部分的SQL查询语法,也是ThinkPHP查询语言的精髓,查询表达式的使用格式:

where('字段名','表达式','查询条件');
whereOr('字段名','表达式','查询条件');

5.1还支持新的查询方法

whereField('表达式','查询条件');
whereOrField('表达式','查询条件');

Field使用字段的驼峰命名方式。

表达式不分大小写,支持的查询表达式有下面几种:

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

注:

1. like查询支持使用数组

Db::name('user')->where('name','like',['%think','php%'],'OR')->select();
//实际生成的SQL语句为
SELECT * FROM `think_user` WHERE  (`name` LIKE '%think' OR `name` LIKE 'php%')

2. between

Db::name('user')->where('id','between','1,8')->select();
//等效
Db::name('user')->where('id','between',[1,8])->select();

3. in

Db::name('user')->where('id','between',[1,8])->select();
//等效
Db::name('user')->where('id','in',[1,5,8])->select();

4. exp

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

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

5. whereField()

Db::name('user')->whereId('>=',100)->select();

六、链式操作

链式操作方法,除了select方法必须放到最后一个外(因为select方法并不是链式操作方法),链式操作的方法调用顺序没有先后

1. where

(1)表达式

Db::table('think_user')
    ->where('id','>',1)
    ->where('name','thinkphp')
    ->select(); 

(2)数组

关联数组

// 传入数组作为查询条件
Db::table('think_user')->where([
	'name'	=>	'thinkphp',
    'status'=>	[1, 2]
])->select(); 

 索引数组

// 传入数组作为查询条件
Db::table('think_user')->where([
	['name','=','thinkphp'],
    ['status','=',1]
])->select(); 

 组装数组

$map[] = ['name','like','think'];
$map[] = ['status','=',1];

(3)字符串

Db::table('think_user')->where('type=1 AND status=1')->select(); 

注意使用字符串查询条件和表达式查询的一个区别在于,不会对查询字段进行避免关键词冲突处理。

2. table

  • 切换操作的数据表;
  • 对多表进行操作;
Db::table('think_user')->where('status>1')->select();
//指定数据库
Db::table('db_name.think_user')->where('status>1')->select();

 

name方式简化数据表前缀的传入,会自动获取当前模型对应的数据表前缀来生成 think_user 数据表名称。

Db::name('user')->where('status>1')->select();

3. alias

用于设置当前数据表的别名,便于使用其他的连贯操作例如join方法等。

Db::table('think_user')
->alias('a')
->join('think_dept b ','b.user_id= a.id')
->select();

//传入数组批量设置数据表以及别名
Db::table('think_user')
->alias(['think_user'=>'user','think_dept'=>'dept'])
->join('think_dept','dept.user_id= user.id')
->select();

//field可以给某个字段设置别名
Db::table('think_user')->field('id,nickname as name')->select();

4. field

//指定字段
Db::table('think_user')->field('id,nickname as name')->select();

//使用SQL函数
Db::table('think_user')->field('id,SUM(score)')->select();

//V5.1.7+版本开始,如果需要使用SQL函数,推荐使用下面的方式
Db::table('think_user')->fieldRaw('id,SUM(score)')->select();

//使用数组参数
Db::table('think_user')->field(['id','title','content'])->select();

//数组方式的定义可以为某些字段定义别名
Db::table('think_user')->field(['id','nickname'=>'name'])->select();

//获取所有字段
Db::table('think_user')->select();
Db::table('think_user')->field('*')->select();

//字段排除
//获取除了content之外的所有字段
Db::table('think_user')->field('content',true)->select();

//用于写入
Db::table('think_user')->field('title,email,content')->insert($data);

5. strict

// 关闭字段严格检查
Db::name('user')
    ->strict(false)
    ->insert($data);

// 关闭严格检查字段是否存在
'fields_strict'  => false,

如果开启字段严格检查的话,在更新和写入数据库的时候,一旦存在非数据表字段的值,则会抛出异常。

6. limit

//限制结果数量
Db::table('think_user')
    ->where('status',1)
    ->field('id,name')
    ->limit(10)
    ->select();
//分页查询
Db::table('think_article')->limit(10,25)->select();

7. page

Db::table('think_article')->limit(25)->page(3)->select();'
//等同于
Db::table('think_article')->page(3,25)->select(); 

8. oder

Db::table('think_user')
->where('status', 1)
->order(['order','id'=>'desc'])
->limit(5)
->select();

//在V5.1.7+版本开始,如果你需要在order方法中使用mysql函数的话,必须使用下面的方式:
Db::table('think_user')
->where('status', 1)
->orderRaw("field(name,'thinkphp','onethink','kancloud')")
->limit(5)
->select();

9. group

Db::table('think_user')
    ->field('user_id,test_time,username,max(score)')
    ->group('user_id,test_time')
    ->select();

10. having

Db::table('think_user')
    ->field('username,max(score)')
    ->group('user_id')
    ->having('count(test_time)>3')
    ->select();

11. join

join ( mixed join [, mixed $condition = null [, string $type = 'INNER']] )
leftJoin ( mixed join [, mixed $condition = null ] )
rightJoin ( mixed join [, mixed $condition = null ] )
fullJoin ( mixed join [, mixed $condition = null ] )

Db::table('think_user')
->alias('a')
->join(['think_work'=>'w'],'a.id=w.artist_id')
->join(['think_card'=>'c'],'a.card_id=c.id')
->select();

12. UNION

操作用于合并两个或多个 SELECT 语句的结果集。

使用示例:

Db::field('name')
    ->table('think_user_0')
    ->union('SELECT name FROM think_user_1')
    ->union('SELECT name FROM think_user_2')
    ->select();
//闭包用法:

Db::field('name')
    ->table('think_user_0')
    ->union(function ($query) {
        $query->field('name')->table('think_user_1');
    })
    ->union(function ($query) {
        $query->field('name')->table('think_user_2');
    })
    ->select();

//或者

Db::field('name')
    ->table('think_user_0')
    ->union([
        'SELECT name FROM think_user_1',
        'SELECT name FROM think_user_2',
    ])
    ->select();

//支持UNION ALL 操作,例如:

Db::field('name')
    ->table('think_user_0')
    ->unionAll('SELECT name FROM think_user_1')
    ->unionAll('SELECT name FROM think_user_2')
    ->select();

//或者

Db::field('name')
    ->table('think_user_0')
    ->union(['SELECT name FROM think_user_1', 'SELECT name FROM think_user_2'], true)
    ->select();



13. distinct

Db::table('think_user')->distinct(true)->field('user_login')->select();

14. cache

//默认情况下, 缓存有效期是由默认的缓存配置参数决定的,但cache方法可以单独指定,例如:
Db::table('think_user')->cache(true,60)->find();
// 或者使用下面的方式 是等效的
Db::table('think_user')->cache(60)->find();
//表示对查询结果的缓存有效期60秒。
//cache方法可以指定缓存标识:
Db::table('think_user')->cache('key',60)->find();
//指定查询缓存的标识可以使得查询缓存更有效率。
//这样,在外部就可以通过\think\Cache类直接获取查询缓存的数据,例如:
$result = Db::table('think_user')->cache('key',60)->find();
$data = \think\Cache::get('key');
//cache方法支持设置缓存标签,例如:
Db::table('think_user')->cache('key',60,'tagName')->find();

七、聚合查询

方法说明
count统计数量,参数是要统计的字段名(可选)
max获取最大值,参数是要统计的字段名(必须)
min获取最小值,参数是要统计的字段名(必须)
avg获取平均值,参数是要统计的字段名(必须)
sum获取总分,参数是要统计的字段名(必须)
Db::table('think_user')->count('id');
Db::table('think_user')->max('score');
//如果你要获取的最大值不是一个数值,可以使用第二个参数关闭强制转换
Db::table('think_user')->max('name',false);
Db::table('think_user')->where('score', '>', 0)->min('name',false);
Db::table('think_user')->avg('score');
Db::table('think_user')->where('id',10)->sum('score');

八、时间查询

1. where

// 大于某个时间
where('create_time', '> time', '2016-1-1');
// 小于某个时间
where('create_time', '<= time', '2016-1-1');
// 时间区间查询
where('create_time', 'between time', ['2015-1-1', '2016-1-1']);

2. 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();

3. whereBetweenTime

// 查询2017年上半年注册的用户
Db::name('user')
    ->whereBetweenTime('create_time', '2017-01-01', '2017-06-30')
    ->select();
// 查询2017年6月1日注册的用户
Db::name('user')
    ->whereBetweenTime('create_time', '2017-06-01')
    ->select();    

4. whereBetweenTimeField

// 查询有效期内的活动
Db::name('event')
	->whereBetweenTimeField('start_time','end_time')
    ->select();
//查询相当于
Db::name('event')
	->whereTime('start_time', '<=', time())
    ->whereTime('end_time', '>=', time())
    ->select();

5. 时间表达式

还提供了更方便的时间表达式查询,例如:

// 获取今天的博客
Db::name('blog')
    ->whereTime('create_time', 'today')
    ->select();
    
// 获取昨天的博客
Db::name('blog')
    ->whereTime('create_time', 'yesterday')
    ->select();
    
// 获取本周的博客
Db::name('blog')
    ->whereTime('create_time', 'week')
    ->select();   
    
// 获取上周的博客
Db::name('blog')
    ->whereTime('create_time', 'last week')
    ->select();    
    
// 获取本月的博客
Db::name('blog')
    ->whereTime('create_time', 'month')
    ->select();   
    
// 获取上月的博客
Db::name('blog')
    ->whereTime('create_time', 'last month')
    ->select();      
    
// 获取今年的博客
Db::name('blog')
    ->whereTime('create_time', 'year')
    ->select();    
    
// 获取去年的博客
Db::name('blog')
    ->whereTime('create_time', 'last year')
    ->select(); 
  
//如果查询当天、本周、本月和今年的时间,还可以简化为:

// 获取今天的博客
Db::name('blog')
    ->whereTime('create_time', 'd')
    ->select();
    
// 获取本周的博客
Db::name('blog')
    ->whereTime('create_time', 'w')
    ->select();   
    
// 获取本月的博客
Db::name('blog')
    ->whereTime('create_time', 'm')
    ->select();   
    
// 获取今年的博客
Db::name('blog')
    ->whereTime('create_time', 'y')
    ->select();    

//时间表达式进行时间查询

  // 查询两个小时内的博客
Db::name('blog')
	->whereTime('create_time','-2 hours')
    ->select();

九、高级查询

1. 快捷查询

快捷查询支持所有的查询表达式。

Db::table('think_user')
    ->where('name|title','like','thinkphp%')
    ->where('create_time&update_time','>',0)
    ->find();

2. 区间查询

区间查询的查询条件必须使用数组定义方式,支持所有的查询表达式。

Db::table('think_user')
    ->where('name', ['like', '%thinkphp%'], ['like', '%kancloud%'], 'or')
    ->where('id', ['>', 0], ['<>', 10], 'and')
    ->find();
//代替
Db::table('think_user')
    ->where('name', 'like', '%think%')
    ->where('name', 'like', '%php%')
    ->where('id', 'in', [1, 5, 80, 50])
    ->where('id', '>', 10)
    ->find();

3. 批量(字段)查询

Db::table('think_user')
    ->where([
        ['name', 'like', 'thinkphp%'],
        ['title', 'like', '%thinkphp'],
        ['id', '>', 0],
        ['status', '=', 1],
    ])
    ->select();

注意,相同的字段的多次查询条件可能会合并,如果希望某一个where方法里面的条件单独处理,可以使用下面的方式,避免被其它条件影响。

$map = [
        ['name', 'like', 'thinkphp%'],
        ['title', 'like', '%thinkphp'],
        ['id', '>', 0],
    ];
Db::table('think_user')
    ->where([ $map ])
    ->where('status',1)
    ->select();

4. 动态查询

动态查询描述
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. 条件查询

Db::name('user')->when($condition, function ($query) {
    // 满足条件后执行
    $query->where('score', '>', 80)->limit(10);
}, function ($query) {
    // 不满足条件执行
    $query->where('score', '>', 60);
});

十、子查询

1. fetchSql

fetchSql方法表示不进行查询而只是返回构建的SQL语句

$subQuery = Db::table('think_user')
    ->field('id,name')
    ->where('id', '>', 10)
    ->fetchSql(true)
    ->select();

2. buildSql

//使用buildSql构造子查询
$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();

3. 使用闭包构造子查询

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

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

十一、原生查询

1. query

Db::query("select * from think_user where status=1");

query方法用于执行SQL查询操作,如果数据非法或者查询错误则返回false,否则返回查询结果数据集(同select方法)。

2. execute

Db::execute("update think_user set name='thinkphp' where status=1");

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

查询事件

一、查询事件

数据库的CURD操作支持事件,包括:

事件描述
before_selectselect查询前回调
before_findfind查询前回调
after_insertinsert操作成功后回调
after_updateupdate操作成功后回调
after_deletedelete操作成功后回调

查询事件仅支持findselectinsertupdatedelete方法。

二、注册事件

使用下面的方法注册数据库查询事件

Db::event('after_insert', 'callback');
Db::event('before_select', function ($query) {
    // 事件处理
    return $result;
});

获取器

Db类也可以支持获取器定义,例如:

Db::name('user')->withAttr('name', function($value, $data) {
	return strtolower($value);
})->select();

上面的代码,查询的数据集数据中的name字段的值会统一进行小写转换。

withAttr方法可以多次调用,对多个字段定义获取器。

事务操作

最简单的方式是使用 transaction 方法操作数据库事务,当闭包中的代码发生异常会自动回滚,例如:

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();
}

注意在事务操作的时候,确保你的数据库连接使用的是同一个。

事务内使用db()无法回滚

存储过程

数据访问层支持存储过程调用,调用数据库存储过程使用下面的方法:

$resultSet = Db::query('call procedure_name');
foreach ($resultSet as $result) {

}

存储过程返回的是一个数据集,如果你的存储过程不需要返回任何的数据,那么也可以使用execute方法:

Db::execute('call procedure_name');

存储过程可以支持输入和输出参数,以及进行参数绑定操作。

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

输出参数的绑定必须额外使用PDO::PARAM_INPUT_OUTPUT,并且可以和输入参数公用一个参数。

无论存储过程内部做了什么操作,每次存储过程调用仅仅被当成一次查询。

数据集

数据库的查询结果也就是数据集,默认的配置下,数据集的类型是一个二维数组,我们可以配置成数据集类,就可以支持对数据集更多的对象化操作,需要使用数据集类功能,可以配置数据库的resultset_type参数

// 数据集返回类型
    'resultset_type' => 'collection',

在模型中进行数据集查询,全部返回数据集对象,但使用的是think\model\Collection类,但用法是一致的。

需要注意的是,如果要判断数据集是否为空,不能直接使用empty判断,而必须使用数据集对象的isEmpty方法判断,例如:

$users = Db::name('user')->select();
if($users->isEmpty()){
    echo '数据集为空';
}
方法描述
isEmpty是否为空
toArray转换为数组
all所有数据
merge合并其它数据
diff比较数组,返回差集
flip交换数据中的键和值
intersect比较数组,返回交集
keys返回数据中的所有键名
pop删除数据中的最后一个元素
shift删除数据中的第一个元素
unshift在数据开头插入一个元素
reduce通过使用用户自定义函数,以字符串返回数组
reverse数据倒序重排
chunk数据分隔为多个数据块
each给数据的每个元素执行回调
filter用回调函数过滤数据中的元素
column返回数据中的指定列
sort对数据排序
shuffle将数据打乱
slice截取数据中的一部分
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值