# 连接数据库
> ThinkPHP内置了抽象数据库访问层,把不同的数据库操作封装起来,我们只需要使用公共的Db类进行操作,而无需针对不同的数据库写不同的代码和底层实现,Db类会自动调用相应的数据库驱动来处理。数据库抽象访问层基于PDO方式,目前内置包含了Mysql、SqlServer、PgSQL、Sqlite等数据库的支持。
如果应用需要使用数据库,必须配置数据库连接信息,数据库的配置文件有多种定义方式。
## 配置文件
在应用配置目录或者模块配置目录(不清楚配置目录位置的话参考配置章节)下面的`database.php`中(后面统称为数据库配置文件)配置下面的数据库参数:
```
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'thinkphp',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'think_',
];
```
系统默认支持的数据库`type`包括:
type数据库mysqlMySQLsqliteSqLitepgsqlPgSQLsqlsrvSqlServer`type`参数支持命名空间完整定义,不带命名空间定义的话,默认采用`\think\db\connector`作为命名空间,如果使用应用自己扩展的数据库驱动,可以配置为:
```
// 数据库类型
'type' => '\org\db\Mysql',
```
表示数据库的连接器采用 `\org\db\Mysql`类作为数据库连接驱动,而不是默认的`\think\db\connector\Mysql`。
每个模块可以设置独立的数据库连接参数,并且相同的配置参数可以无需重复设置,例如我们可以在`admin`模块的数据库配置文件中定义:
```
return [
// 服务器地址
'hostname' => '192.168.1.100',
// 数据库名
'database' => 'admin',
];
```
表示`admin`模块的数据库地址改成 `192.168.1.100`,数据库名改成`admin`,其它的连接参数和应用的`database.php`中的配置一样。
ThinkPHP`5.1`支持数据库的断线重连机制(默认关闭),需要的话,在数据库配置文件中设置:
```
// 开启断线重连
'break_reconnect' => true,
```
### 连接参数
可以针对不同的连接需要添加数据库的连接参数(具体的连接参数可以参考PHP手册),内置采用的参数包括如下:
```
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES => false,
```
在数据库配置文件中设置的`params`参数中的连接配置将会和内置的设置参数合并,如果需要使用长连接,并且返回数据库的小写列名,可以在数据库配置文件中增加下面的定义:
```
'params' => [
\PDO::ATTR_PERSISTENT => true,
\PDO::ATTR_CASE => \PDO::CASE_LOWER,
],
```
> 你可以在`params`参数里面配置任何PDO支持的连接参数。
## 方法配置
我们可以调用`Db::connect`方法动态配置数据库连接信息,例如:
```
Db::connect([
// 数据库类型
'type' => 'mysql',
// 数据库连接DSN配置
'dsn' => '',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'thinkphp',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'think_',
]);
```
或者使用字符串方式:
```
Db::connect('mysql://root:1234@127.0.0.1:3306/thinkphp#utf8');
```
> `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');
Db::connect('db_config2');
```
动态连接数据库的`connect`方法仅对当次查询有效。
> 这种方式的动态连接和切换数据库比较方便,经常用于多数据库连接的应用需求。
## 模型类定义
如果某个模型类里面定义了`connection`属性的话,则该模型操作的时候会自动按照给定的数据库配置进行连接,而不是配置文件中设置的默认连接信息,例如:
```
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 直接使用配置参数名
protected $connection = 'db_config1';
}
```
和前面一种方法配置一样,`connection`属性可以支持数组和字符串方式。
> 需要注意的是,ThinkPHP的数据库连接是惰性的,所以并不是在实例化的时候就连接数据库,而是在有实际的数据操作的时候才会去连接数据库。
## 数据库调试模式
无论应用是否部署模式,数据库有自己独立的调试模式开关,数据库配置参数中的`debug`参数就是数据库调试模式的开关(默认关闭)。
```
// 数据库调试模式
'debug' => true,
```
数据库调试模式开启后,可以支持下列行为:
- 记录SQL日志;
- 分析SQL性能;
- 支持SQL监听;
由于上述行为不可避免会产生额外的开销,因此对性能存在一定的影响,但并不大,因为所有的日志是最终统一一次性写入,而且可以设置为某个用户才写入日志。
> 在生产模式下面,必须关闭应用调试模式(`app_debug`),否则会暴露你的服务器敏感信息。和应用调试模式不同,开启数据库调试模式并不会对外暴露任何安全信息,因此是否开启数据库调试模式,看自己的需求。
## 配置参数参考
下面是默认支持的数据库连接信息:
参数名描述默认值type数据库类型无hostname数据库地址127.0.0.1database数据库名称无username数据库用户名无password数据库密码无hostport数据库端口号无dsn数据库连接dsn信息无params数据库连接参数空charset数据库编码utf8prefix数据库的表前缀无debug是否调试模式falsedeploy数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)0rw\_separate数据库读写是否分离 主从式有效falsemaster\_num读写分离后 主服务器数量1slave\_no指定从服务器序号无fields\_strict是否严格检查字段是否存在trueresultset\_type数据集返回类型arrayauto\_timestamp自动写入时间戳字段falsesql\_explain是否需要进行SQL性能分析 开启调试有效falsequery指定查询对象think\\db\\Query常用数据库连接参数(`params`)可以参考[PHP在线手册](http://php.net/manual/zh/pdo.constants.php)中的以`PDO::ATTR_`开头的常量。
如果同时定义了 参数化数据库连接信息 和 dsn信息,则会优先使用dsn信息。
> #### 注意:
>
> - - - - - -
>
> 如果是使用`pgsql`数据库驱动的话,请先导入 `thinkphp/library/think/db/connector/pgsql.sql`文件到数据库执行。
## 断线重连
如果你使用的是长连接或者命令行,在超出一定时间后,数据库连接会断开,这个时候你需要开启断线重连才能确保应用不中断。
在数据库配置文件中,设置:
```
// 开启断线重连
'break_reconnect' => true,
```
开启后,系统会自动判断数据库断线并尝试重新连接。大多数情况下都能自动识别,`V5.1.6+`版本以上如果在一些特殊的情况下或者某些数据库驱动的断线标识错误还没有定义,支持配置下面的信息:
```
// 断线标识字符串
'break_match_str' => [
'error with',
],
```
在 `break_match_str`配置中加入你的数据库错误信息关键词。
- 序言
- 基础
- 安装
- 开发规范
- 目录结构
- 配置
- 架构
- 架构总览
- 入口文件
- URL访问
- 模块设计
- 命名空间
- 容器和依赖注入
- Facade
- 钩子和行为
- 中间件
- 路由
- 路由定义
- 变量规则
- 路由地址
- 闭包支持
- 路由参数
- 路由缓存
- 跨域请求
- 注解路由
- 路由分组
- MISS路由
- 资源路由
- 快捷路由
- 路由别名
- 路由绑定
- 域名路由
- URL生成
- 控制器
- 控制器定义
- 前置操作
- 跳转和重定向
- 空操作和空控制器
- 分层控制器
- 资源控制器
- 请求
- 请求对象
- 请求信息
- 输入变量
- 请求类型
- HTTP头信息
- 伪静态
- 参数绑定
- 请求缓存
- 响应
- 响应输出
- 响应参数
- 重定向
- 数据库
- 连接数据库
- 查询构造器
- 查询数据
- 添加数据
- 更新数据
- 删除数据
- 查询表达式
- 链式操作
- 聚合查询
- 时间查询
- 高级查询
- 视图查询
- JSON字段
- 子查询
- 原生查询
- 查询事件
- 事务操作
- 监听SQL
- 存储过程
- 数据集
- 分布式数据库
- 模型
- 定义
- 新增
- 更新
- 删除
- 查询
- JSON字段
- 获取器
- 修改器
- 自动时间戳
- 只读字段
- 软删除
- 类型转换
- 数据完成
- 查询范围
- 模型输出
- 模型事件
- 模型关联
- 一对一关联
- 一对多关联
- 远程一对多
- 多对多关联
- 多态关联
- 关联预载入
- 关联统计
- 关联输出
- 视图
- 视图渲染
- 视图赋值
- 视图过滤
- 模板引擎
- 模板
- 变量输出
- 使用函数
- 运算符
- 原样输出
- 模板注释
- 模板布局
- 模板继承
- 包含文件
- 输出替换
- 标签库
- 内置标签
- 循环标签
- 比较标签
- 条件判断
- 资源文件加载
- 标签嵌套
- 原生PHP
- 定义标签
- 标签扩展
- 错误和日志
- 异常处理
- 日志处理
- 调试
- 调试模式
- Trace调试
- 性能调试
- SQL调试
- 变量调试
- 远程调试
- 验证
- 验证器
- 验证规则
- 错误信息
- 验证场景
- 路由验证
- 内置规则
- 独立验证
- 静态调用
- 表单令牌
- 杂项
- 缓存
- Session
- Cookie
- 多语言
- 分页
- 上传
- 命令行
- 启动内置服务器
- 自动生成目录结构
- 创建类库文件
- 生成类库映射文件
- 清除缓存文件
- 生成配置缓存文件
- 生成数据表字段缓存
- 生成路由映射缓存
- 自定义指令
- 扩展库
- 验证码
- 图像处理
- Time
- 数据库迁移工具
- Workerman
- MongoDb
- 单元测试
- 安全和性能
- 安全建议
- 优化建议
- 附录
- 助手函数
- 升级指导
- 更新日志