当前位置: 首页 > news >正文

ThinkPHP8学习篇(五):数据库(一)

在请求流程中,数据库是数据存储与交互的核心载体,所有业务数据的持久化、读取与变更都依赖于数据库操作。而数据库连接是开展一切数据库操作的前提,查询构造器则为基础的增删改查提供了便捷、安全的实现方式。所以本篇作为数据库系列文章的第一篇,学习的核心内容将集中在数据库连接配置、查询构造器的基本使用以及基础的新增、查询、更新、删除操作上。本篇文章将记录 ThinkPHP 数据库连接与查询构造器基础增删改查的学习过程。

一、连接数据库

1、配置文件

2、切换连接

3、模型类定义

4、配置参数参考

5、关闭连接

二、查询构造器

1、查询数据

1.1、查询单个数据

1.2、查询数据集

1.3、值和列查询

1.4、游标查询

2、添加数据

2.1、添加一条数据

2.2、添加多条数据

3、更新数据

4、删除数据


一、连接数据库

数据库和模型操作采用独立的 ThinkORM 库,默认安装应用的时候会自动安装。

如果应用需要使用数据库,必须配置数据库连接信息。

1、配置文件

在配置目录(config)下面的 database.php 中(后面统称为数据库配置文件)配置数据库参数:

return [// 默认使用的数据库连接配置'default'         => env('DB_DRIVER', 'mysql'),// 自定义时间查询规则'time_query_rule' => [],// 自动写入时间戳字段// true为自动识别类型 false关闭// 字符串则明确指定时间字段类型 支持 int timestamp datetime date'auto_timestamp'  => true,// 时间字段取出后的默认时间格式'datetime_format' => 'Y-m-d H:i:s',// 时间字段配置 配置格式:create_time,update_time'datetime_field'  => '',// 数据库连接配置信息'connections'     => ['mysql' => [// 数据库类型'type'            => env('DB_TYPE', 'mysql'),// 服务器地址'hostname'        => env('DB_HOST', '127.0.0.1'),// 数据库名'database'        => env('DB_NAME', ''),// 用户名'username'        => env('DB_USER', 'root'),// 密码'password'        => env('DB_PASS', ''),// 端口'hostport'        => env('DB_PORT', '3306'),// 数据库连接参数'params'          => [],// 数据库编码'charset'         => env('DB_CHARSET', 'utf8mb4'),// 数据库表前缀'prefix'          => env('DB_PREFIX', ''),// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)'deploy'          => 0,// 数据库读写是否分离 主从式有效'rw_separate'     => false,// 读写分离后 主服务器数量'master_num'      => 1,// 指定从服务器序号'slave_no'        => '',// 是否严格检查字段是否存在'fields_strict'   => true,// 是否需要断线重连'break_reconnect' => false,// 监听SQL'trigger_sql'     => env('APP_DEBUG', true),// 开启字段缓存'fields_cache'    => false,],// 更多的数据库配置信息],
];

采用多类型的方式配置,方便切换数据库。

default 配置用于设置默认使用的数据库连接配置(默认使用的连接配置为 mysql)。

connections 配置具体的数据库连接信息,default 配置参数定义的连接配置必须要存在。

connections 配置连接信息中的 type 参数用于指定数据库类型,可以指定的数据库类型如下表所示:

type

数据库

mysql

MySQL

sqlite

SqLite

pgsql

PostgreSQL

sqlsrv

SqlServer

mongo

MongoDb

oracle

Oracle

2、切换连接

我们可以在数据库配置文件中定义多个连接信息:

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

可以调用 Db::connect(连接名称) 方法动态配置数据库连接信息,例如:

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

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

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

3、模型类定义

如果某个模型类里面定义了 connection 属性的话,则该模型操作的时候会自动按照给定的数据库配置进行连接,而不是配置文件中设置的默认连接信息,例如:

<?php
namespace app\index\model;use think\Model;class User extends Model
{protected $connection = 'demo'; // 使用的数据库连接是 demo 的配置
}

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

4、配置参数参考

参数名

描述

默认值

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

trigger_sql

是否开启SQL监听

true

auto_timestamp

自动写入时间戳字段

false

query

指定查询对象

think\db\Query

5、关闭连接

在常驻内存的服务模式下使用 ThinkORM,我们可能需要手动关闭连接。close() 方法用于关闭数据库连接。

Db::connect()->close();

二、查询构造器

查询构造器是ORM中最核心的部分,ThinkORM 查询构造器为数据库查询提供了统一、安全、灵活并且优雅的查询机制,内置支持PDO参数绑定,可用于执行大多数数据库的CURD操作,并封装了包括聚合查询、分页查询、时间查询等常用查询方法,还可以配合原生查询语句完成复杂的查询。

在使用查询构造器的时候,需要使用门面调用:

use think\facade\Db;

1、查询数据

在使用查询构造器的时候,确保已经引入了门面类(后续的代码中不再做引入的说明,但是不要忘记引入):

use think\facade\Db;

1.1、查询单个数据

find 方法用于查询单个数据。查询结果不存在,返回 null,否则返回结果数组。

// table 方法必须指定完整的数据表名
// 查询 user 表中 id=1 的数据
Db::table('user')->where('id', 1)->find();
// 生成的SQL语句是:SELECT * FROM `user` WHERE  `id` = 1 LIMIT 1

如果希望查询数据不存在的时候返回空数组而不是 null,可以使用 findOrEmpty 方法:

Db::table('user')->where('id', 1)->findOrEmpty();

注意:如果没有任何的查询条件并且也没有调用 order 方法的话 ,find 查询不会返回任何结果。

1.2、查询数据集

select 方法用于查询多个数据(数据集)。

// 查询 user 表中 status=1 的数据
Db::table('user')->where('status', 1)->select();

select 方法查询结果是一个数据集对象(think\Collection),如果需要转换为数组可以使用 toArray 方法:

Db::table('user')->where('status', 1)->select()->toArray();
/* 返回的数据格式为:[['id'=>1, 'name'='zhangsan', age=18, status=1, ...],['id'=>2, 'name'='lisi', age=25, status=1, ...],]
*/

如果希望在没有查找到数据后抛出异常可以使用 selectOrFail 方法:

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

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

findselect 方法之前可以使用所有的链式操作(在后续的文章中记录)方法。

1.3、值和列查询

value 方法用于查询某个字段的值。查询结果不存在,返回 null。

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

column 方法用于查询某一列的值。查询结果不存在,返回空数组。

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

如果要返回所有列数据,并且添加一个索引值的话,可以在 column 方法中传入 "*":

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

值查询和列查询的区别

  • 值查询(value):始终返回单个值(不是数组),且仅返回查询结果中第一条记录的指定字段值。即使查询条件能匹配多条记录,也只会取第一条的对应字段值。
  • 列查询(column):返回一个数组,数组中包含查询结果里所有记录的指定字段值(可能是一个或多个值)。如果查询结果为空,会返回空数组;如果只有一条记录,会返回包含一个元素的数组。

1.4、游标查询

如果需要处理大量的数据,可以使用新版提供的游标查询功能,该查询方式利用了PHP的生成器特性,可以大幅减少大量数据查询的内存开销问题。

cursor 方法用于游标查询,返回一个生成器对象。

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

2、添加数据

2.1、添加一条数据

save 方法用于统一写入数据,自动判断是新增还是更新数据(以写入数据中是否存在主键数据为判断依据)。

$data = ['name' => 'wangwu', 'age' => 17, 'status' => 1]; // 保存的数据
Db::table('user')->save($data);

也可以使用 insert 方法向数据库写入数据。写入数据成功返回写入成功的条数,通常情况返回 1。

$data = ['name' => 'wangwu', 'age' => 17, 'status' => 1];
Db::table('user')->insert($data);

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

$data = ['name' => 'wangwu', 'age' => 17, 'status' => 1];
$userId = Db::table('user')->insertGetId($data);

2.2、添加多条数据

insertAll 方法用于向数据库写入多条数据,传入需要写入的数据(通常是二维数组)即可。写入数据成功返回写入成功的条数。

$data = [['name' => 'wangwu', 'age' => 17, 'status' => 1],['name' => 'wangwu1', 'age' => 18, 'status' => 1],['name' => 'wangwu2', 'age' => 19, 'status' => 1],
];
Db::table('user')->insertAll($data);

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

$data = [['name' => 'wangwu', 'age' => 17, 'status' => 1],['name' => 'wangwu1', 'age' => 18, 'status' => 1],['name' => 'wangwu2', 'age' => 19, 'status' => 1],...
];
// 分批写入 每次最多100条数据
Db::table('user')->limit(100)->insertAll($data);

3、更新数据

可以使用 save 方法更新数据。

// 更新的数据中需要包含更新数据的主键id
$data = ['id' => 1, 'name' => '张三'];
Db::table('user')->save($data);

也可以使用 update 方法更新数据。update 方法返回影响数据的条数,没修改任何数据返回 0。

Db::table('user')->where('id', 1)->update(['name' => 'zhangsan']); // 以关联数组的形式传入更改的数据

如果更新的数据中包含主键,可以直接在 update 方法中使用:

Db::table('user')->update(['name' => 'zhangsan', 'id' => 1]); // 和上面示例的效果是一样的

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

Db::table('user')->where('id', 1)             // 设置条件->exp('name', 'UPPER(name)') // 设置更新字段与数据,可以使用SQL函数或者其它字段->update();                  // 调用更新方法

支持使用 raw 方法进行数据更新,它允许在查询中直接使用原生SQL片段。

Db::table('user')->where('id', 1)->update(['name' => Db::raw('UPPER(name)'), // SQL片段:name 字段的值更改为大写'age' => Db::raw('age + 2')       // SQL片段:age 字段的值在原有基础上加2]);

注意:使用 Db::raw 时,需要特别注意安全性问题,尤其是SQL注入的风险。因为 Db::raw 允许直接插入原生SQL片段,如果这些片段来自于用户输入或其他不可信的源,那么它们可能会包含恶意SQL代码,从而导致SQL注入攻击。

4、删除数据

delete 方法用于删除数据。可以直接向该方法传入删除数据的主键,也可以根据条件进行数据删除。delete 方法返回影响数据的条数,没有删除返回 0。

// 根据主键删除
Db::table('user')->delete(1);            // 根据一个主键进行删除
Db::table('user')->delete([1, 2, 3]);    // 如果删除的数据为多条,那么传入的为主键数组// 条件删除
Db::table('user')->where('id', 1)->delete();          // 删除 id=1 的数据
Db::table('user')->where('id', '<', 10)->delete();    // 删除 id<10 的数据

如果确定需要删除数据表中所有数据,可以向 delete 方法中传入 true 参数。

Db::table('user')->delete(true);

注意:如果不带任何条件调用 delete 方法会提示错误。

一般情况下,业务数据是不建议真实删除的,ThinkPHP 提供了软删除机制。useSoftDelete 方法用于软删除。

// 软删除数据 使用 status 字段标记删除,status=1 为删除数据
Db::table('user')->where('id', 1)->useSoftDelete('status', 1)->delete();
http://www.xdnf.cn/news/1413829.html

相关文章:

  • 洛谷p2392kkksc03考前临时抱佛脚 详解(回溯,深度搜索法)
  • Redis常见数据类型及应用场景
  • java 安装流程配置
  • 金仓数据库KingbaseES:中国自主原创的数据库领军者
  • 【四位加密】2022-10-25
  • GDPU操作系统实验:生产者消费者问题
  • 【读数笔记】《你的生存本能正在杀死你》
  • 经典卷积神经网络CNN
  • sublime MAC系统快捷键及常见问题
  • Qwen2.5-VL代码初步解读
  • 恒香全新旗舰店开幕 新店传承百年文化
  • 容器seccomp配置文件在云服务器安全策略中的实施规范
  • 常用定位技术对比解析
  • MySQL数据库——0.MySQL大纲
  • 【全功能图片处理工具详解】基于Streamlit的现代化图像处理解决方案
  • OpenCV 图像轮廓检测
  • 【系统分析师】高分论文:论面向服务方法在信息系统开发中的应用
  • 基于CotSegNet网络和机器学习的棉花点云器官分割和表型信息提取
  • 获取某天的零点日期
  • 解锁GPU计算潜能:深入浅出CUDA架构与编程模型
  • Day18 (前端:JavaScript基础阶段)
  • Langflow 评估与迭代技术深度分析
  • Cookie、Session 和 JWT
  • git中使用SSH的配置
  • 堆排序:高效稳定的大数据排序法
  • 【图论】 Graph.jl 概览
  • 面试问题详解十三:Qt 多线程同步【QReadWriteLock】讲解
  • 24数学建模国赛C
  • 【数据分享】上市公司-国际化程度-营业收入指标(2005-2023)
  • Linux软件升级方法总结