• hyperf 三十一 极简DB组件


    一 安装及配置

    1. composer require hyperf/db
    2. php bin/hyperf.php vendor:publish hyperf/db

    默认配置 config/autoload/db.php 如下,数据库支持多库配置,默认为 default

    配置项类型默认值备注
    driverstring数据库引擎 支持 pdomysql
    hoststringlocalhost数据库地址
    portint3306数据库地址
    databasestring数据库默认 DB
    usernamestring数据库用户名
    passwordstringnull数据库密码
    charsetstringutf8数据库编码
    collationstringutf8_unicode_ci数据库编码
    fetch_modeintPDO::FETCH_ASSOCPDO 查询结果集类型
    pool.min_connectionsint1连接池内最少连接数
    pool.max_connectionsint10连接池内最大连接数
    pool.connect_timeoutfloat10.0连接等待超时时间
    pool.wait_timeoutfloat3.0超时时间
    pool.heartbeatint-1心跳
    pool.max_idle_timefloat60.0最大闲置时间
    optionsarrayPDO 配置

     具体接口可以查看 Hyperf\DB\ConnectionInterface

    方法名返回值类型备注
    beginTransactionvoid开启事务 支持事务嵌套
    commitvoid提交事务 支持事务嵌套
    rollBackvoid回滚事务 支持事务嵌套
    insertint插入数据,返回主键 ID,非自增主键返回 0
    executeint执行 SQL,返回受影响的行数
    queryarray查询 SQL,返回结果集列表
    fetcharray, object查询 SQL,返回结果集的首行数据
    connectionself指定连接的数据库

    二 使用

    1. #使用 DB 实例
    2. use Hyperf\Context\ApplicationContext;
    3. use Hyperf\DB\DB;
    4. $db = ApplicationContext::getContainer()->get(DB::class);
    5. $res = $db->query('SELECT * FROM `user` WHERE gender = ?;', [1]);
    6. #使用静态方法
    7. use Hyperf\DB\DB;
    8. $res = DB::query('SELECT * FROM `user` WHERE gender = ?;', [1]);
    9. #使用匿名函数自定义方法
    10. #此种方式可以允许用户直接操作底层的 PDO 或者 MySQL,所以需要自己处理兼容问题
    11. use Hyperf\DB\DB;
    12. $sql = 'SELECT * FROM `user` WHERE id = ?;';
    13. $bindings = [2];
    14. $mode = \PDO::FETCH_OBJ;
    15. $res = DB::run(function (\PDO $pdo) use ($sql, $bindings, $mode) {
    16. $statement = $pdo->prepare($sql);
    17. $this->bindValues($statement, $bindings);
    18. $statement->execute();
    19. return $statement->fetchAll($mode);
    20. });

    三 测试

    1. use Hyperf\DB\DB as AustereDb;
    2. use Hyperf\Utils\ApplicationContext;
    3. public function testdb1() {
    4. $db = ApplicationContext::getContainer()->get(AustereDb::class);
    5. $res = $db->query('SELECT * FROM `push_recode` WHERE id = ?;', [1]);
    6. var_dump($res);
    7. $res = AustereDb::query('SELECT * FROM `push_recode` WHERE id = ?;', [1]);
    8. var_dump($res);
    9. $sql = 'SELECT * FROM `push_recode` WHERE id = ?;';
    10. $bindings = [1];
    11. $mode = \PDO::FETCH_NUM;
    12. $res = AustereDb::run(function (\PDO $pdo) use ($sql, $bindings, $mode) {
    13. $statement = $pdo->prepare($sql);
    14. $this->bindValues($statement, $bindings);
    15. $statement->execute();
    16. return $statement->fetchAll($mode);
    17. });
    18. var_dump($res);
    19. }

     测试结果

    1. array(1) {
    2. [0]=>
    3. array(4) {
    4. ["id"]=>
    5. int(1)
    6. ["is_push"]=>
    7. int(1)
    8. ["push_time"]=>
    9. string(19) "2024-04-11 08:10:13"
    10. ["created_at"]=>
    11. NULL
    12. }
    13. }
    14. array(1) {
    15. [0]=>
    16. array(4) {
    17. ["id"]=>
    18. int(1)
    19. ["is_push"]=>
    20. int(1)
    21. ["push_time"]=>
    22. string(19) "2024-04-11 08:10:13"
    23. ["created_at"]=>
    24. NULL
    25. }
    26. }
    27. array(1) {
    28. [0]=>
    29. array(4) {
    30. [0]=>
    31. int(1)
    32. [1]=>
    33. int(1)
    34. [2]=>
    35. string(19) "2024-04-11 08:10:13"
    36. [3]=>
    37. NULL
    38. }
    39. }

    可能由于版本问题,Hyperf\Context\ApplicationContext类不存在,所以使用Hyperf\Utils\ApplicationContext。

    使用三种方法查询数据,使用DB实例、使用静态方法、使用PDO。

    四 原理

    获取容器参考hyperf console 执行-CSDN博客

    数据库配置获取参考hyperf console 执行-CSDN博客

    用 php bin/hyperf.php vendor:publish hyperf/db 创建配置文件config\autoload\db.php后,其中使用.env文件。所以若项目数据库在.env中设置,配置文件可以不用改。

    使用静态方法也是先获取容器,再调用对应方法。

    使用run方法是根据配置文件获取数据库连接驱动,获取对应链接,默认是pdo。

    若驱动为mysql,实际运行Hyperf\DB\MySQLConnection::run(Closure $closure)。

    Closure类为一个闭包。

    五 源码

    1. #config\autoload\db.php
    2. return [
    3. 'default' => [
    4. 'driver' => 'pdo',
    5. 'host' => env('DB_HOST', 'localhost'),
    6. 'port' => env('DB_PORT', 3306),
    7. 'database' => env('DB_DATABASE', 'hyperf'),
    8. 'username' => env('DB_USERNAME', 'root'),
    9. 'password' => env('DB_PASSWORD', ''),
    10. 'charset' => env('DB_CHARSET', 'utf8mb4'),
    11. 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
    12. 'fetch_mode' => PDO::FETCH_ASSOC,
    13. 'pool' => [
    14. 'min_connections' => 1,
    15. 'max_connections' => 10,
    16. 'connect_timeout' => 10.0,
    17. 'wait_timeout' => 3.0,
    18. 'heartbeat' => -1,
    19. 'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
    20. ],
    21. 'options' => [
    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. ];
    1. #Hyperf\DB\DB
    2. protected $poolName;
    3. public function __construct(PoolFactory $factory, string $poolName = 'default')
    4. {
    5. $this->factory = $factory;
    6. $this->poolName = $poolName;
    7. }
    8. public static function __callStatic($name, $arguments)
    9. {
    10. $container = ApplicationContext::getContainer();
    11. $db = $container->get(static::class);
    12. return $db->{$name}(...$arguments);
    13. }
    14. public function __call($name, $arguments)
    15. {
    16. $hasContextConnection = Context::has($this->getContextKey());
    17. $connection = $this->getConnection($hasContextConnection);
    18. try {
    19. $connection = $connection->getConnection();
    20. $result = $connection->{$name}(...$arguments);
    21. } catch (Throwable $exception) {
    22. $result = $connection->retry($exception, $name, $arguments);
    23. } finally {
    24. if (! $hasContextConnection) {
    25. if ($this->shouldUseSameConnection($name)) {
    26. // Should storage the connection to coroutine context, then use defer() to release the connection.
    27. Context::set($contextKey = $this->getContextKey(), $connection);
    28. defer(function () use ($connection, $contextKey) {
    29. Context::set($contextKey, null);
    30. $connection->release();
    31. });
    32. } else {
    33. // Release the connection after command executed.
    34. $connection->release();
    35. }
    36. }
    37. }
    38. return $result;
    39. }
    40. private function getContextKey(): string
    41. {
    42. return sprintf('db.connection.%s', $this->poolName);
    43. }
    44. protected function getConnection(bool $hasContextConnection): AbstractConnection
    45. {
    46. $connection = null;
    47. if ($hasContextConnection) {
    48. $connection = Context::get($this->getContextKey());
    49. }
    50. if (! $connection instanceof AbstractConnection) {
    51. $pool = $this->factory->getPool($this->poolName);
    52. $connection = $pool->get();
    53. }
    54. return $connection;
    55. }
    1. #Hyperf\DB\Pool\PoolFactory
    2. protected $container;
    3. public function __construct(ContainerInterface $container)
    4. {
    5. $this->container = $container;
    6. }
    7. public function getPool(string $name)
    8. {
    9. if (isset($this->pools[$name])) {
    10. return $this->pools[$name];
    11. }
    12. $config = $this->container->get(ConfigInterface::class);
    13. $driver = $config->get(sprintf('db.%s.driver', $name), 'pdo');
    14. $class = $this->getPoolName($driver);
    15. $pool = make($class, [$this->container, $name]);
    16. if (! $pool instanceof Pool) {
    17. throw new InvalidDriverException(sprintf('Driver %s is not invalid.', $driver));
    18. }
    19. return $this->pools[$name] = $pool;
    20. }
    21. protected function getPoolName(string $driver)
    22. {
    23. switch (strtolower($driver)) {
    24. case 'mysql':
    25. return MySQLPool::class;
    26. case 'pdo':
    27. return PDOPool::class;
    28. }
    29. if (class_exists($driver)) {
    30. return $driver;
    31. }
    32. throw new DriverNotFoundException(sprintf('Driver %s is not found.', $driver));
    33. }
    1. #Hyperf\DB\Pool\MySQLPool
    2. protected function createConnection(): ConnectionInterface
    3. {
    4. return new MySQLConnection($this->container, $this, $this->config);
    5. }
  • 相关阅读:
    Latex常用宏包\usepackage
    windows 安装 Android Studio
    java计算机毕业设计健康医疗预约系统MyBatis+系统+LW文档+源码+调试部署
    0动态规划中等 LeetCode467. 环绕字符串中唯一的子字符串
    python控制流-循环
    pytorch collate_fn测试用例
    MySQL 约束
    操作系统微内核和宏内核
    HTTP2指纹识别(一种相对不为人知的网络指纹识别方法)
    java毕业设计阿博图书馆管理系统mybatis+源码+调试部署+系统+数据库+lw
  • 原文地址:https://blog.csdn.net/lsswear/article/details/137927619