hyperf 三十一 极简DB组件

embedded/2024/9/24 1:40:12/

一 安装及配置

composer require hyperf/db
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指定连接的数据库

二 使用

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

三 测试

php">use Hyperf\DB\DB as AustereDb;
use Hyperf\Utils\ApplicationContext;public function testdb1() {$db = ApplicationContext::getContainer()->get(AustereDb::class);$res = $db->query('SELECT * FROM `push_recode` WHERE id = ?;', [1]);var_dump($res);$res = AustereDb::query('SELECT * FROM `push_recode` WHERE id = ?;', [1]);var_dump($res);$sql = 'SELECT * FROM `push_recode` WHERE id = ?;';$bindings = [1];$mode = \PDO::FETCH_NUM;$res = AustereDb::run(function (\PDO $pdo) use ($sql, $bindings, $mode) {$statement = $pdo->prepare($sql);$this->bindValues($statement, $bindings);$statement->execute();return $statement->fetchAll($mode);});var_dump($res);
}

 测试结果

php">array(1) {[0]=>array(4) {["id"]=>int(1)["is_push"]=>int(1)["push_time"]=>string(19) "2024-04-11 08:10:13"["created_at"]=>NULL}
}
array(1) {[0]=>array(4) {["id"]=>int(1)["is_push"]=>int(1)["push_time"]=>string(19) "2024-04-11 08:10:13"["created_at"]=>NULL}
}
array(1) {[0]=>array(4) {[0]=>int(1)[1]=>int(1)[2]=>string(19) "2024-04-11 08:10:13"[3]=>NULL}
}

可能由于版本问题,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类为一个闭包。

五 源码

php">#config\autoload\db.php
return ['default' => ['driver' => 'pdo','host' => env('DB_HOST', 'localhost'),'port' => env('DB_PORT', 3306),'database' => env('DB_DATABASE', 'hyperf'),'username' => env('DB_USERNAME', 'root'),'password' => env('DB_PASSWORD', ''),'charset' => env('DB_CHARSET', 'utf8mb4'),'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),'fetch_mode' => PDO::FETCH_ASSOC,'pool' => ['min_connections' => 1,'max_connections' => 10,'connect_timeout' => 10.0,'wait_timeout' => 3.0,'heartbeat' => -1,'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),],'options' => [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,],],
];
php">#Hyperf\DB\DBprotected $poolName;public function __construct(PoolFactory $factory, string $poolName = 'default'){$this->factory = $factory;$this->poolName = $poolName;}public static function __callStatic($name, $arguments){$container = ApplicationContext::getContainer();$db = $container->get(static::class);return $db->{$name}(...$arguments);}public function __call($name, $arguments){$hasContextConnection = Context::has($this->getContextKey());$connection = $this->getConnection($hasContextConnection);try {$connection = $connection->getConnection();$result = $connection->{$name}(...$arguments);} catch (Throwable $exception) {$result = $connection->retry($exception, $name, $arguments);} finally {if (! $hasContextConnection) {if ($this->shouldUseSameConnection($name)) {// Should storage the connection to coroutine context, then use defer() to release the connection.Context::set($contextKey = $this->getContextKey(), $connection);defer(function () use ($connection, $contextKey) {Context::set($contextKey, null);$connection->release();});} else {// Release the connection after command executed.$connection->release();}}}return $result;}private function getContextKey(): string{return sprintf('db.connection.%s', $this->poolName);}protected function getConnection(bool $hasContextConnection): AbstractConnection{$connection = null;if ($hasContextConnection) {$connection = Context::get($this->getContextKey());}if (! $connection instanceof AbstractConnection) {$pool = $this->factory->getPool($this->poolName);$connection = $pool->get();}return $connection;}
php">#Hyperf\DB\Pool\PoolFactoryprotected $container;public function __construct(ContainerInterface $container){$this->container = $container;}public function getPool(string $name){if (isset($this->pools[$name])) {return $this->pools[$name];}$config = $this->container->get(ConfigInterface::class);$driver = $config->get(sprintf('db.%s.driver', $name), 'pdo');$class = $this->getPoolName($driver);$pool = make($class, [$this->container, $name]);if (! $pool instanceof Pool) {throw new InvalidDriverException(sprintf('Driver %s is not invalid.', $driver));}return $this->pools[$name] = $pool;}protected function getPoolName(string $driver){switch (strtolower($driver)) {case 'mysql':return MySQLPool::class;case 'pdo':return PDOPool::class;}if (class_exists($driver)) {return $driver;}throw new DriverNotFoundException(sprintf('Driver %s is not found.', $driver));}
php">#Hyperf\DB\Pool\MySQLPoolprotected function createConnection(): ConnectionInterface{return new MySQLConnection($this->container, $this, $this->config);}

http://www.ppmy.cn/embedded/13119.html

相关文章

centos7服务器系统如何安装宋体字文件

centos7服务器系统如何安装宋体字文件! 最近开发的积德寺app,菩提佛堂祈福平台网站发布后,由于服务器之前遇到了攻击,数据丢失了,重新安装了一遍系统centos7.发现客户的功德证书创建后,字体乱码了。很明显是缺少了宋体…

c++ 智能指针 指针数据监控实验

1.概要 std::weak_ptr 是一种智能指针,通常不单独使用,只能和 shared_ptr 类型指针搭配使用,可以视为 shared_ptr 指针的一种辅助工具。借助 weak_ptr 类型指针可以获取 shared_ptr 指针的一些状态信息,比如有多少指向相同的 sha…

bash test.sh 2>1 是什么意思?

bash test.sh > test.log 2>&1 &这个命令是在后台运行一个名为 test.sh 的 Bash 脚本,并将该脚本的标准错误输出(stderr,用2来表示)重定向到标准输出(stdout,用1来表示)&#xff…

1688跨境寻源通代采系统

1688代采系统:一键开启高效采购新时代 随着电子商务的快速发展,传统的采购模式已经难以满足现代企业的需求。面对海量的商品信息和复杂的采购流程,企业往往陷入困境。然而,随着我们研发的1688代采系统的推出,这一切问…

【kettle002】kettle访问人大金仓KingbaseES数据库并处理数据至execl文件

一直以来想写下基于kettle的系列文章,作为较火的数据ETL工具,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 熟悉、梳理、总结下人大金仓KingbaseES数据库相关知识体系 kettle访问人大金仓KingbaseES数据库…

【Git系列】rebase的使用场景

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Mysql 锁学习笔记

目录 Innodb锁 共享锁与排它锁 锁兼容级别 意向锁 - 表级锁 代码示例 表级锁类型兼容性 行锁 代码示例 间隙锁 代码示例 临键锁 - 行锁加间隙锁 插入意向锁 自增锁 SELECT的加锁规则 (RR) 查看锁状态命令 3.0 前置条件 3.1 主键检索 3.2 唯一索引检索 3.3 普…

去雾笔记01-SRKTDN: Applying Super Resolution Method to Dehazing Task

文章目录 Abstract1. Introduction2. Related Work3. Method3.1. Network Architecture Abstract 们提出了一种结合超分辨方法和知识转移方法的模型。我们的模型由一个教师网络、一个去雾网络和一个超分辨率网络组成。 1. Introduction ECNU KT团队提出了一个知识蒸馏[20]模…