快速开始

前言

hyperf/database 衍生于 illuminate/database,我们对它进行了一些改造,大部分功能保持了相同。在这里感谢一下 Laravel 开发组,实现了如此强大好用的 ORM 组件。

hyperf/database 组件是基于 illuminate/database 衍生出来的组件,我们对它进行了一些改造,从设计上是允许用于其它 PHP-FPM 框架或基于 Swoole 的框架中的,而在 Hyperf 里就需要提一下 hyperf/db-connection 组件,它基于 hyperf/pool 实现了数据库连接池并对模型进行了新的抽象,以它作为桥梁,Hyperf 才能把数据库组件及事件组件接入进来。

安装

Hyperf 框架

  1. composer require hyperf/db-connection

其它框架

  1. composer require hyperf/database

配置

默认配置如下,数据库支持多库配置,默认为 default

配置项类型默认值备注
driverstring数据库引擎
hoststring数据库地址
databasestring数据库默认DB
usernamestring数据库用户名
passwordstringnull数据库密码
charsetstringutf8数据库编码
collationstringutf8_unicode_ci数据库编码
prefixstring''数据库模型前缀
pool.min_connectionsint1连接池内最少连接数
pool.max_connectionsint10连接池内最大连接数
pool.connect_timeoutfloat10.0连接等待超时时间
pool.wait_timeoutfloat3.0超时时间
pool.heartbeatint-1心跳
pool.max_idle_timefloat60.0最大闲置时间
optionsarrayPDO 配置
  1. <?php
  2. return [
  3. 'default' => [
  4. 'driver' => env('DB_DRIVER', 'mysql'),
  5. 'host' => env('DB_HOST', 'localhost'),
  6. 'database' => env('DB_DATABASE', 'hyperf'),
  7. 'username' => env('DB_USERNAME', 'root'),
  8. 'password' => env('DB_PASSWORD', ''),
  9. 'charset' => env('DB_CHARSET', 'utf8'),
  10. 'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),
  11. 'prefix' => env('DB_PREFIX', ''),
  12. 'pool' => [
  13. 'min_connections' => 1,
  14. 'max_connections' => 10,
  15. 'connect_timeout' => 10.0,
  16. 'wait_timeout' => 3.0,
  17. 'heartbeat' => -1,
  18. 'max_idle_time' => (float)env('DB_MAX_IDLE_TIME', 60),
  19. ]
  20. ],
  21. ];

有时候用户需要修改 PDO 默认配置,比如所有字段需要返回为 string。这时候就需要修改 PDO 配置项 ATTR_STRINGIFY_FETCHES 为 true。

  1. <?php
  2. return [
  3. 'default' => [
  4. 'driver' => env('DB_DRIVER', 'mysql'),
  5. 'host' => env('DB_HOST', 'localhost'),
  6. 'database' => env('DB_DATABASE', 'hyperf'),
  7. 'username' => env('DB_USERNAME', 'root'),
  8. 'password' => env('DB_PASSWORD', ''),
  9. 'charset' => env('DB_CHARSET', 'utf8'),
  10. 'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),
  11. 'prefix' => env('DB_PREFIX', ''),
  12. 'pool' => [
  13. 'min_connections' => 1,
  14. 'max_connections' => 10,
  15. 'connect_timeout' => 10.0,
  16. 'wait_timeout' => 3.0,
  17. 'heartbeat' => -1,
  18. 'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
  19. ],
  20. 'options' => [
  21. // 框架默认配置
  22. PDO::ATTR_CASE => PDO::CASE_NATURAL,
  23. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  24. PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
  25. PDO::ATTR_STRINGIFY_FETCHES => false,
  26. PDO::ATTR_EMULATE_PREPARES => false,
  27. ],
  28. ],
  29. ];

读写分离

有时候你希望 SELECT 语句使用一个数据库连接,而 INSERTUPDATE,和 DELETE 语句使用另一个数据库连接。在 Hyperf 中,无论你是使用原生查询,查询构造器,或者是模型,都能轻松的实现

为了弄明白读写分离是如何配置的,我们先来看个例子:

  1. <?php
  2. return [
  3. 'default' => [
  4. 'driver' => env('DB_DRIVER', 'mysql'),
  5. 'read' => [
  6. 'host' => ['192.168.1.1'],
  7. ],
  8. 'write' => [
  9. 'host' => ['196.168.1.2'],
  10. ],
  11. 'sticky' => true,
  12. 'database' => env('DB_DATABASE', 'hyperf'),
  13. 'username' => env('DB_USERNAME', 'root'),
  14. 'password' => env('DB_PASSWORD', ''),
  15. 'charset' => env('DB_CHARSET', 'utf8'),
  16. 'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),
  17. 'prefix' => env('DB_PREFIX', ''),
  18. 'pool' => [
  19. 'min_connections' => 1,
  20. 'max_connections' => 10,
  21. 'connect_timeout' => 10.0,
  22. 'wait_timeout' => 3.0,
  23. 'heartbeat' => -1,
  24. 'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
  25. ],
  26. ],
  27. ];

注意在以上的例子中,配置数组中增加了三个键,分别是 readwritestickyreadwrite 的键都包含一个键为 host 的数组。而 readwrite 的其他数据库都在键为 mysql 的数组中。

如果你想重写主数组中的配置,只需要修改 readwrite 数组即可。所以,这个例子中: 192.168.1.1 将作为 「读」 连接主机,而 192.168.1.2 将作为 「写」 连接主机。这两个连接会共享 mysql 数组的各项配置,如数据库的凭据(用户名 / 密码),前缀,字符编码等。

sticky 是一个 可选值,它可用于立即读取在当前请求周期内已写入数据库的记录。若 sticky 选项被启用,并且当前请求周期内执行过 「写」 操作,那么任何 「读」 操作都将使用 「写」 连接。这样可确保同一个请求周期内写入的数据可以被立即读取到,从而避免主从延迟导致数据不一致的问题。不过是否启用它,取决于应用程序的需求。

执行原生SQL查询

配置好数据库后,便可以使用 Hyperf\DbConnection\Db 进行查询。

Select 查询

select 方法将始终返回一个数组,数组中的每个结果都是一个 StdClass 对象

  1. <?php
  2. use Hyperf\DbConnection\Db;
  3. $users = Db::select('SELECT * FROM `user` WHERE gender = ?',[1]);
  4. foreach($users as $user){
  5. echo $user->name;
  6. }

运行插入语句

可以使用 Dbinsert 方法来执行 insert 语句。与 select 一样,该方法将原生 SQL 查询作为其第一个参数,并将绑定数据作为第二个参数:

  1. <?php
  2. use Hyperf\DbConnection\Db;
  3. Db::insert('insert into user (id, name) values (?, ?)', [1, 'Hyperf']);

运行更新语句

update 方法用于更新数据库中现有的记录。该方法返回受该语句影响的行数:

  1. <?php
  2. use Hyperf\DbConnection\Db;
  3. $affected = Db::update('update user set name = ? where id = ?', ['John', 1]);

数据库事务

你可以使用 Dbtransaction 方法在数据库事务中运行一组操作。如果事务的闭包 Closure 中出现一个异常,事务将会回滚。如果事务闭包 Closure 执行成功,事务将自动提交。一旦你使用了 transaction , 就不再需要担心手动回滚或提交的问题:

  1. <?php
  2. use Hyperf\DbConnection\Db;
  3. Db::transaction(function () {
  4. Db::table('user')->update(['votes' => 1]);
  5. Db::table('posts')->delete();
  6. });

手动使用事务

如果你想要手动开始一个事务,并且对回滚和提交能够完全控制,那么你可以使用 DbbeginTransaction, commit, rollBack:

  1. use Hyperf\DbConnection\Db;
  2. Db::beginTransaction();
  3. try{
  4. // Do something...
  5. Db::commit();
  6. } catch(\Throwable $ex){
  7. Db::rollBack();
  8. }