hyperf 三十一 极简DB组件

一 安装及配置

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指定连接的数据库

二 使用

#使用 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);
});

三 测试

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);
}

 测试结果

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类为一个闭包。

五 源码

#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,],],
];
#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;}
#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));}
#Hyperf\DB\Pool\MySQLPoolprotected function createConnection(): ConnectionInterface{return new MySQLConnection($this->container, $this, $this->config);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/644365.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【软件安装】(十六)双系统Ubuntu22.04引导启动菜单的默认项

一个愿意伫立在巨人肩膀上的农民...... 好学的人总是喜欢在电脑上安装双系统,可是安装好系统之后,就会出现默认启动优先级的苦恼,如果在Bios中设置Windows引导启动为优先启动,那么每次想要进如Ubuntu系统就都需要重新设置Bios。如…

通过Bedrock Access Gateway解决方案快速访问Amazon Bedrock的多种大语言模型

Bedrock Access Gateway(BAG)解决方案提供了开箱即用、兼容 OpenAI 的代理功能,帮助用户轻松无缝地从 OpenAI 迁移到 Amazon Bedrock。 1. 概述 亚马逊云科技的 Amazon Bedrock 服务支持一系列领先的基础模型,为客户提供多种选择…

CSS3:border-image

<!DOCTYPE html> <html><head><meta charset"utf-8"> </head><body><p>原始图片</p><img src"./images/border1.png" alt""><p>一、</p><p>border: 27px solid transp…

【解决NodeJS项目无法在IDEA中调试的问题】使用JetBrains IDEA 2023 调试nodejs项目

项目采用Ant Design Pro React&#xff0c;使用前后端分离开发方式&#xff0c;后端可以很容易的打断点调试&#xff0c;但是前端通过网页进行调试&#xff0c;在IDEA中加了调试断点&#xff0c;但是没有什么用处。 解决方案如下&#xff1a; 点击新建运行配置 新建JavaScrip…

【Linux】实现一个进度条

我们之前也学了gcc/vim/make和makefile&#xff0c;那么我们就用它们实现一个进度条。 在实现这个进度条之前&#xff0c;我们要先简单了解一下缓冲区和回车和换行的区别 缓冲区其实就是一块内存空间&#xff0c;我们先看这样一段代码 它的现象是先立马打印&#xff0c;三秒后程…

网络安全主题纪录片

网络安全主题纪录片 文章目录 网络安全主题纪录片第四公民黑客帝国系列龙纹身女孩碟中谍系列虎胆龙威4匿名者终结者2&#xff1a;审判日东方快车谋杀案黑客国家公敌我是谁&#xff1a;没有绝对安全的系统黑客军团速度与激情系列十亿美元大劫案勒索软件的背后黑客的恐惧为什么网…

web前端框架设计第六课-样式绑定

web前端框架设计第六课-样式绑定 一.预习笔记 1.class属性绑定 给P标签绑定一个类样式&#xff0c;类名为active。当active取值为true时&#xff0c;表示绑定样式成功&#xff0c;取值为false时&#xff0c;取消绑定 以对象形式给P标签绑定多个类样式 以数组形式给P标签绑定多…

使用linux,c++,创作一个简单的五子棋游戏

#include <iostream> #include <vector> #include <unordered_map> using namespace std; // 棋盘大小 const int BOARD_SIZE 15; // 棋子类型 enum ChessType { EMPTY, BLACK, WHITE }; // 棋盘类 class ChessBoard { private: vect…

全氟己酮灭火绳的用法早知道:灭火绳多少钱一米?

全氟己酮灭火装置作为一种高效、安全、环保的灭火技术&#xff0c;已经成为了备受青睐的新型灭火选择之一。伴随着市场需求不断增长&#xff0c;在全氟己酮厂家的努力下&#xff0c;各式各样的全氟己酮自动灭火装置不断涌现&#xff0c;包括自动灭火贴、灭火片、灭火毯、灭火绳…

go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控

有关包的安装 我们要实现go语言对第三方包的操作需要我们下载第三方包go.etcd.io&#xff0c;下载命令&#xff1a; go get go.etcd.io/etcd/client/v3 ectd的put与get操作 相关函数说明与示例 我们想实现对etcd进行简单的操作的步骤还是比较简单的&#xff0c;在我上一篇文…

图像哈希:全局+局部提取特征

文章信息 作者&#xff1a;梁小平&#xff0c;唐振军期刊&#xff1a;ACM Trans. Multimedia Comput. Commun. Appl&#xff08;三区&#xff09;题目&#xff1a;Robust Hashing via Global and Local Invariant Features for Image Copy Detection 目的、实验步骤及结论 目…

python实现钉钉通讯录导出Excel表

Python工具开源专栏 Py0004 python实现钉钉通讯录导出Excel表 Python工具开源专栏前言目录结构部分演示完整代码已在GitHub上开源 前言 需求来源于公司&#xff0c;需要将钉钉通讯录以Excel表的形式导出到本地&#xff0c;方便定期备份。导出的Excel需要处理钉钉用户兼任多部门…