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\DB

protected $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\PoolFactory

protected $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\MySQLPool

protected function createConnection(): ConnectionInterface
    {
        return new MySQLConnection($this->container, $this, $this->config);
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python_django中小学家校互动系统vue_flask家校联系

实现了一个完整的家校互动系统,其中主要有作业信息模块、学校管理员模块、学生学籍模块、学生成绩模块、学科模块、系统新闻模块、系统公告模块、校内新闻模块、校内公告模块、用户表模块、token表模块、关于我们模块、收藏表模块、年级模块、家长模块、教师模块、互…

贪心算法练习day.1

理论基础 贪心算法是一种常见的解决优化问题的方法,其基本思想就是在问题的每个决策阶段,都选择当前看起来最优的选择,即贪心地做出局部的最优决策,以此得到全局的最优解,例如在十张面额不同的钞票,让我们…

mysql-connector 交叉编译

1.下载 官网选择对应的系统以及版本,这里我用的是6.1.5https://downloads.mysql.com/archives/c-c/ 2.解压 tar -zxvf mysql-connector-c-6.1.5-src.tar.gz 3.先常规编译(因为交叉编译的过程中,会用到生成的二进制文件) cd m…

PCB元器件的符号和封装

打开立创商店: PCB是用来链接器件和让电路小型化的 符号: 封装: 封装是在PCB板上呈现的方式 紫色:不需要上绿由 红色: 焊盘 黄色: 丝印层 也就是白色的这个 焊盘 焊盘是为了让接触点增大,更好的焊接元件 焊盘…

ardupilot开发 --- 机载(边缘)计算机-VISP高阶 篇

让我再看你一眼从南到北 0. 基础1. 视觉伺服1.1 视觉伺服基础1.1.1 基本理论1.1.2 代码解析(tutorial-ibvs-4pts.cpp): 1.2 基于图像处理的视觉伺服 0. 基础 基础知识点请参考基础篇。 1. 视觉伺服 参考:Visual servoing 1.1 视觉伺服基础 参考1&am…

达芬奇调色:色彩理论入门

写在前面 整理一些达芬奇调色的笔记博文内容涉及: 一级调色是什么,以及 调色素材格式 log,raw,rec709 简单认知理解不足小伙伴帮忙指正 不必太纠结于当下,也不必太忧虑未来,当你经历过一些事情的时候&#…

全网最全搭建Electron项目的各种方式及错误解决

一、官方文档手动搭建 文档地址:快速入门 | Electron,按照文档步骤操作即可,项目只包含了Electron依赖,仅仅只是一个hello world展示。 二、github上拉取官网的electron-quick-start项目 electron-quick-start跟方式一创建的一…

MySQL数据库运维:运行监控及解决sql执行死锁问题

前言 在现代数据密集型应用程序的开发和部署中,MySQL数据库的运维是至关重要的环节之一。一个良好设计和维护的MySQL数据库系统可以确保数据的准确性、可靠性和高效的访问,从而支持业务的顺利运行。然而,随着业务规模的增长和复杂性增加&…

Spring 5源码学习

文章目录 一. 访问[spring官网], 找到Spring Framework,点击红色标记github仓库,下载对应的分支代码,本人下载5.1.x二. 安装gradle三. 调整spring-framework配置四. 开始编译五.导入idea 一. 访问[spring官网], 找到Spring Framework&#xf…

使用Python和wxPython下载视频封面

介绍: 在在线视频内容的世界中,是领先的平台。拥有数十亿的视频,拥有引人注目的封面图像非常重要,以吸引观众。在本博客文章中,我们将探讨如何使用Python和wxPython模块下载视频封面。我们将提供两个代码示例&#xff…

图像数据做并行规约时,如何确定共享内存和网格的大小

做并行规约时,如何确定共享内存和网格的大小 1、为什么要确定共享内存和网格大小2、共享内存大小定义3、网格大小 注:1、这里记录使用笔记,不对cuda的名词做解释,没有详细数学原理和代码。 2、环境:cuda8.0&#xff0c…

密码学 | Random Oracle 随机预言机

​ 🥑原文:究竟什么才是随机预言机呢? - 玄星的回答 🥑答主指出: 英文维基明明对 随机预言机 给出了两个完全不同的理解,但这两个理解之间的连接词却是 “Stated differently”,即 “换句话说…

STM32通过ESP8266(MQTT)连接新版ONENET(2024/4/23)(保姆级教程)附运行结果

⏩ 大家好哇!我是小光,想要成为系统架构师的嵌入式爱好者。 ⏩在各种嵌入式系统中我们经常会使用上位机去做显示,本文对STM32通过ESP8266连接最新版的ONENET做一个详细教程。 ⏩感谢你的阅读,不对的地方欢迎指正。 STM32通过ESP82…

【图说】VMware Ubuntu22.04 详细安装教程

前言 无论是从事 Linux 开发工作,还是希望电脑运行双系统,VMware 虚拟机都是我们日常工作不可或缺的工具。本章将会重点介绍 VMware 安装流程,以及在 VMware 上如何运行、使用 Ubuntu22.04 系统。 一、VMware 下载安装 1.1 VMware 官网下载…

如何查看西门子触摸屏的镜像版本?

如何查看西门子触摸屏的镜像版本? 当软件组态的设备版本和实际设备镜像之间版本不同时,那么在传输项目时就会出现兼容性冲突的提示。 镜像版本说明: 如何调整镜像版本(升级或降级)? 为了使用新功能以及提高面板的稳定性、可靠性和可用性,建议使用新的镜像版本。 一、 通…

目标检测算法是指什么?

一、目标检测算法是指什么? 目标检测算法是计算机视觉领域的一个重要分支,它旨在识别和定位图像中的目标对象。以下是目标检测算法的相关内容: 目标检测的核心问题:目标检测需要解决的两个核心问题是“目标是什么”和“目标在哪里…

【计算机网络】(三)物理层 - 通信基础

文章目录 【计算机网络】(三)物理层 - 通信基础前言3.1 物理层的基本概念3.2 数据通信的基础知识3.2.1 数据、信号、码元3.2.2 信源、信宿、信道3.2.3 编码、调制3.2.3.1 基带调制(编码)3.2.3.2 带通调制(调制&#xf…

想搭建跨境电商网站?掌握这些源码关键点,助您轻松上线

随着全球化的发展和电子商务的兴盛,跨境电商已成为企业拓展国际市场的主要方式之一。然而,想要搭建一个成功的跨境电商网站并非易事,其中关键之一就是掌握跨境电商网站源码的要点。在本文中,我将为您深入探讨如何选择、优化和维护…

一个java项目中,如何使用sse协议,构造一个chatgpt的流式对话接口

前言 如何注册chatGPT,怎么和它交互,本文就不讲了;因为网上教程一大堆,而且你要使用的话,通常会再包一个算法服务,用来做一些数据训练和过滤处理之类的,业务服务基本不会直接与原生chatGPT交互。…

mysql-connector-java和spring-boot-starter-jdbc和mybatis-spring-boot-start

mysql-connector-java和spring-boot-starter-jdbc和mybatis-spring-boot-start JDBC是什么意思? JDBC是使用java语言操作mysql数据库的规范,java语言必须按照这个规范写才可以操作mysql数据库。 mysql-connector-java 在最开始的时候 程序中是不允许…