9.ThinkPHP数据库操作

Posted 余生随缘~~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9.ThinkPHP数据库操作相关的知识,希望对你有一定的参考价值。

连接数据库

在应用配置目录或者模块配置目录下面的config/database.php中配置下面的数据库参数

image-20200525162437983

image-20200525162443245

注:配置好的,一定要检查mysql服务是否开启,同时也要检查pdo是否打开。

同时还是创建好对应的数据库和连接数据库的用户名和密码并确保他们可以连接上你们的mysql服务器。

读取配置文件中的配置

例:

<?php

namespace app\\index\\controller;

use think\\Controller;

class Db extends Controller
{
    public function db(){
    	//database文件中的prefix选项
        echo config(\'database.prefix\');
    }
}

访问结果

image-20200525163516481

执行原生的sql

db类查询方法

Db类支持原生SQL查询操作,主要包括下面两个方法:

方法名 作用
query方法 query方法用于执行SQL查询操作,如果数据非法或者查询错误则返回false,否则返回查询结果数据集(同select方法)
execute方法 execute用于更新和写入数据的sql操作,如果数据非法或者查询错误则返回false,否则返回影响的记录数。

参数绑定

支持在原生查询的时候使用参数绑定,包括问号占位符或者命名占位符,例如:

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

用法示例

方式一

<?php

namespace app\\index\\controller;

use think\\Controller;
use \\think\\Db as mdb;

class Db extends Controller
{
    public function db(){
        //?为占位符
        $sql = "select * from tp_articles where id=?";
        $res = mdb::query($sql,[102]);
        dump($res);
    }
}

方式二

<?php

namespace app\\index\\controller;

use think\\Controller;
//注意引入会报错所以重命名一下
use \\think\\Db as mdb;

class Db extends Controller
{
    public function db(){
        //:id为占位符
        //如果一定要写原生sql,推荐写此关联数组占位
        $sql = "select * from tp_articles where id=:id";
        $res = mdb::query($sql,[\'id\' => 102]);
        dump($res);
    }
}

以上两种方式运行结果为:

image-20200525164352008

添加数据

单条数据插入

要添加的数据

$data = [\'title\' => \'我是标题111\', \'desn\' => \'我是描述\', \'body\' => \'bbbb\'];

注意:方式一和方式二都要引入\\think\\Db

例:

use \\think\\Db;

方式一:Db::table 需要写全表名称

例:

// 添加一条数据
// 返回影响的行数
// table写全表名称
$ret = Db::table(\'tp_articles\')->insert($data);

方式二:Db::name 可以不写前缀

// name可以不写表前缀
$ret = Db::name(\'articles\')->insert($data);

方式三:db()可以不写前缀,也不用引入db类

$ret = db(\'articles\') -> insert($data) ;

注意上面三种运行后返回的都是影响的行数

运行结果

image-20200525171755076

返回插入成功的主键ID

$ret = db(\'articles\') -> insertGetId($data) ;

运行结果

image-20200525171938790

多条数据插入

要添加的数据

# 添加多条数据
$data = [
            [\'title\' => \'1111\', \'body\' => \'aaa\'],
            [\'title\' => \'2222\', \'body\' => \'bbb\'],
            [\'title\' => \'3333\', \'body\' => \'ccc\']
        ];

方式一:Db::name(\'表名\')->insertAll($data)

//先引入
use \\think\\Db;

$res = Db::name(\'articles\')->insertAll($data);

image-20200525174023178

方式二:db(\'表名\')->insertAll($data)

$res = db(\'articles\')->insertAll($data);

image-20200525174202820

更新数据

全字段更新

方式一:db()->where()->update()方式

写法示例:

#写法1 推荐 注意如果where条件中间是=号,则可以省略不写
db(\'user\')->where(\'id\', \'=\', 205)->update([\'name\' => \'thinkphp\']);

#写法2
db(\'user\')->where(\'id\', \'=\', 205)->data([\'name\' => \'thinkphp\'])->update();

#写法3 这种写法需要主键是id
Db::name(\'user\')->update([\'name\' => \'thinkphp\',\'id\'=>1]);

例:

public function update(){
        // 修改数据
        $data = [\'title\' => \'我是标题111\', \'desn\' => \'我是描述\', \'body\' => \'bbbb\'];
        //$res = db(\'articles\')->where(\'id\', \'=\', \'205\')->update($data);

        $data = [\'id\' => \'205\',\'title\' => \'我是标题111\', \'desn\' => \'我是描述\', \'body\' => \'bbbb\'];
        $res = db(\'articles\')->update($data);
        dump($res);
    }

运行结果

image-20200525181937131

方式二:Db::raw 数值类型字段更新

V5.1.7+版本以后,支持使用raw方法进行数据更新,适合在数组更新的情况。

注意Db::raw支持表达式,字符串是用Db::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\')
    ]);

例:

$res = Db::name(\'articles\')
            ->where(\'id\',206)
            ->update([
                \'click\' => Db::raw(\'click+1\')
            ]);

运行结果

image-20200525185928749

单字段更新

setField() 更新单个字段

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

最终生成的SQL语句可能如下:

UPDATE `think_user`  SET `name` = \'thinkphp\'  WHERE  `id` = 1

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

setInc/setDec 自增或自减一个字段的值

可以使用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);

最终生成的SQL语句可能是:

UPDATE `think_user`  SET `score` = `score` + 1  WHERE  `id` = 1 
UPDATE `think_user`  SET `score` = `score` + 5  WHERE  `id` = 1
UPDATE `think_user`  SET `score` = `score` - 1  WHERE  `id` = 1
UPDATE `think_user`  SET `score` = `score` - 5  WHERE  `id` = 1 

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

# 无条件删除所有数据  小心去用
Db::name(\'user\')->delete(true);

# 软删除数据 使用delete_time字段标记删除   逻辑删除
# 软删除,必须要表中要delete_time字段,且该字段因为存放的是时间戳所以应该是int
Db::name(\'user\')
	->where(\'id\', 1)
	->useSoftDelete(\'delete_time\',time())
    ->delete();

直接删除示例

image-20200525193905789

软删除示例

public function del(){
       
        # 软删除数据 使用delete_time字段标记删除   逻辑删除
        # 软删除,必须要表中要delete_time字段 且该字段因为存放的是时间戳所以应该是int
        $res = Db::name(\'articles\')
            ->where(\'id\', 207)
            ->useSoftDelete(\'delete_time\',time())
            ->delete();
        dump($res);
    }

image-20200525194715742

查询数据

相关方法API和作用

方法 作用 示例
find() 查询单个数据 // table方法必须指定完整的数据表名
Db::table(\'think_user\')->where(\'id\',1)->find();
findOrFail() 如果希望在没有找到数据后抛出异常可以使用 如果没有查找到数据,则会抛出一个think\\db\\exception\\DataNotFoundException异常
Db::table(\'think_user\')->where(\'id\',1)->findOrFail();
findOrEmpty() V5.1.23+版本开始,支持,当查询不存在的时候返回空数组而不是Null Db::table(\'think_user\')->where(\'id\',1)->findOrEmpty()
select() 查询多个数据(数据集)使用 Db::table(\'think_user\')->where(\'status\',1)->select()
selectOrFail() 如果希望在没有查找到数据后抛出异常可以使用 如果没有查找到数据,同样也会抛出一个think\\db\\exception\\DataNotFoundException异常
Db::table(\'think_user\')->where(\'status\',1)->selectOrFail()
value() 查询某个字段的值可以用,value 方法查询结果不存在,返回 null // 返回某个字段的值
Db::table(\'think_user\')->where(\'id\',1)->value(\'name\');
column() 查询某一列的值可以用,column 方法查询结果不存在,返回空数组 // 返回数组
Db::table(\'think_user\')->where(\'status\',1)->column(\'name\');
// 指定id字段的值作为索引,也就是让id作为键name为值
Db::table(\'think_user\')->where(\'status\',1)->column(\'name\',\'id\');
// 指定id字段的值作为索引 返回所有数据 Db::table(\'think_user\')->where(\'status\',1)->column(\'*\',\'id\');
order() 排序
limit() 取某个范围的值

单条件查询

注意:上面的方法都能用,这里只是做个例子

例:

public function select(){
    //$res = db(\'articles\')->where(\'id\',\'=\', 102)->find();
    $res = db(\'articles\')->where(\'id\',\'>\', 200)->select();
    dump($res);
}

image-20200525223834057

多条件查询

例:

public function select(){
        //id 大于100,click大于100
        //方式一
        //$res = db(\'articles\')->where(\'id\',\'>\', 100)->where(\'click\', \'>\', 100)->select();

        //方式二
        /*$where = [
            [\'id\', \'>\', 100],
            [\'click\', \'>\', 100]
        ];
        $res = db(\'articles\')->where($where)->select();*/

        //方式三
        /*$where = [
            \'id\' => [\'>\', 100],
            \'click\' => [\'>\', 100]
        ];
        $obj = new Where($where);
        $res = db(\'articles\')->where($obj)->select();*/
        //方式四 闭包查询
        //注意:这种方式sql会解析成这样,进行了条件分组
        //如:SELECT * FROM `tp_articles` WHERE ( `id` > 100 AND `click` > 100 ) OR ( `id` > 100 AND `click` > 100 )
        //上面的三种方式则不会,会直接解析成,没有进行条件分组
        //如: SELECT * FROM `tp_articles` WHERE `id` > 100 AND `click` > 100
        $res = db(\'articles\')->where(function (Query $query){
            $query->where(\'id\',\'>\', 100)->where(\'click\', \'>\', 100);
        })->whereOr(function (Query $query){
            $query->where(\'id\',\'>\', 100)->where(\'click\', \'>\', 100);
        })->select();
        dump($res);
    }

image-20200525225914914

where条件 and,or,in

where方法的用法是ThinkPHP查询语言的精髓,也是ThinkPHP ORM的重要组成部分和亮点所在,可以完成包括普通查询、表达式查询、快捷查询、区间查询、组合查询在内的查询操作。where方法的参数支持的变量类型包括字符串、数组和闭包。

where方法相同用法的方法还包括whereOrwhereIn等一系列快捷查询方法,下面仅以where为例说明用法。

AND

主要用于等值AND条件,例如:

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

最后生成的SQL语句是

SELECT * FROM think_user WHERE `name`=\'thinkphp\' AND status = 1

IN

V5.1.13+版本开始增加了关联数组的IN查询支持,例如可以使用:

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

最后生成的SQL语句是

SELECT * FROM think_user WHERE `name`=\'thinkphp\' AND status IN (1, 2)

OR

$res = db(\'articles\')->where(function (Query $query){
	$query->where(\'id\',\'>\', 100)->where(\'click\', \'>\', 100);
})->whereOr(function (Query $query){
	$query->where(\'id\',\'>\', 100)->where(\'click\', \'>\', 100);
})->select();

最后生成的SQL语句是

SELECT * FROM `tp_articles` WHERE ( `id` > 100 AND `click` > 100 ) OR ( `id` > 100 AND `click` > 100 )

字符串条件

使用字符串条件直接查询和操作,例如:

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

最后生成的SQL语句是

SELECT * FROM think_user WHERE type=1 AND status=1

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

使用字符串条件的时候,如果需要传入变量,建议配合预处理机制,确保更加安全,例如:

Db::table(\'think_user\')
->where("id=:id and username=:name", [\'id\' => [1, \\PDO::PARAM_INT] , \'name\' => \'thinkphp\'])
->select();

或者使用

Db::table(\'think_user\')
->where("id=:id and username=:name")
->bind([\'id\' => [1, \\PDO::PARAM_INT] , \'name\' => \'thinkphp\'])
->select();

V5.1.7+版本以后,你可以使用更安全的

Db::table(\'think_user\')
->whereRaw("id=:id and username=:name", [\'id\' => [1, \\PDO::PARAM_INT] , \'name\' => \'thinkphp\'])
->select();

排序和分页

$res = db(\'articles\')->order(\'id\', \'desc\')->limit(0,2)->select();

例:

image-20200525231532819

聚合查询

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

方法 说明
count 统计数量,参数是要统计的字段名(可选)
max 获取最大值,参数是要统计的字段名(必须)
min 获取最小值,参数是要统计的字段名(必须)
avg 获取平均值,参数是要统计的字段名(必须)
sum 获取总分,参数是要统计的字段名(必须)

聚合方法如果没有数据,默认都是0,聚合查询都可以配合其它查询条件

V5.1.5+版本开始,聚合查询可以支持JSON字段类型

用法示例

获取用户数:

Db::table(\'think_user\')->count();

实际生成的SQL语句是:

SELECT COUNT(*) AS tp_count FROM `think_user` LIMIT 1

或者根据字段统计:

Db::table(\'think_user\')->count(\'id\');

生成的SQL语句是:

SELECT COUNT(id) AS tp_count FROM `think_user` LIMIT 1

获取用户的最大积分:

Db::table(\'think_user\')->max(\'score\');

生成的SQL语句是:

SELECT MAX(score) AS tp_max FROM `think_user` LIMIT 1

如果你要获取的最大值不是一个数值,可以使用第二个参数关闭强制转换

Db::table(\'think_user\')->max(\'name\',false);

获取积分大于0的用户的最小积分:

Db::table(\'think_user\')->where(\'score\', \'>\', 0)->min(\'score\');

和max方法一样,min也支持第二个参数用法

Db::table(\'think_user\')->where(\'score\', \'>\', 0)->min(\'name\',false);

获取用户的平均积分:

Db::table(\'think_user\')->avg(\'score\');

生成的SQL语句是:

SELECT AVG(score) AS tp_avg FROM `think_user` LIMIT 1

统计用户的总成绩:

Db::table(\'think_user\')->where(\'id\',10)->sum(\'score\');

生成的SQL语句是:

SELECT SUM(score) AS tp_sum FROM `think_user` LIMIT 1

获取器(V5.1.20+

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

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

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

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

支持对JSON字段定义获取器,例如:

$user = Db::name(\'user\')
	->json([\'info\'])
    ->withAttr(\'info.name\', function($value, $data) {
        return strtolower($value);
    })->find(1);
dump($user);    

查询结果返回的时候,会自动对info字段(JSON字段)的name属性使用获取器操作。

例:

//获取器                                            当前数据,数据源
$res = db(\'articles\')->withAttr(\'title\',function ($value,$data){
    //重新编辑的数据
    return \'获取器-----\'.$value;
})->where(\'id\',\'>\', 200)->select();

运行结果

image-20200525233500620

以上是关于9.ThinkPHP数据库操作的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

VSCode 如何操作用户自定义代码片段(快捷键)

代码片段 - Golang 实现集合操作

Apollo Codegen 没有找到生成代码的操作或片段