hyperf 三十一 极简DB组件

news2024/11/16 16:28:01

一 安装及配置

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线程安全以及解决方案

文章目录 1.线程安全的原因①抢占式执行②多线程修改同一个变量③修改的操作不是原子的④内存可见性⑤指令重排序 2. 线程安全的解决方案3 synchronized的特性------可重入锁 1.线程安全的原因 ①抢占式执行 操作系统对线程的调度是随机的,没有规律(主…

什么便签好用又没广告 好用无广便签分享

身处这个快节奏的时代,我们时常被各种琐事和计划所包围。想象一下,你在办公桌前,电脑屏幕上杂乱无章地贴着各种纸质便签,有的记录着待办事项,有的则是灵感闪现时的几句诗句。每次想要查找某个信息,都得费力…

Golang | Leetcode Golang题解之第42题接雨水

题目&#xff1a; 题解: func trap(height []int) (ans int) {n : len(height)if n 0 {return}leftMax : make([]int, n)leftMax[0] height[0]for i : 1; i < n; i {leftMax[i] max(leftMax[i-1], height[i])}rightMax : make([]int, n)rightMax[n-1] height[n-1]for i…

CANoe-Vector Security Manager介绍

Vector Security Manager 是 Vector 公司提供的一种工具,它为像 CANoe 这样的 Vector 工具提供安全功能,例如安全相关的通信(SecOC)、诊断、认证等,这些功能都是在安全配置文件中进行管理的。所有支持的工具都采用统一的配置方式。 一个安全配置文件为工具提供了以下安全…

探索AI时代的新天地:LLAMA3引领人工智能革命

大家好&#xff01;相信大家对于AI&#xff08;人工智能&#xff09;的发展已经有了一定的了解&#xff0c;但你是否意识到&#xff0c;到了2024年&#xff0c;AI已经变得如此强大和普及&#xff0c;带来了我们从未想象过的便利和创新呢&#xff1f;让我们一起来看看AI在这个时…

如何安全高效地进行网点文件下发?

随着IT技术的飞速发展&#xff0c;以银行为代表的企业数字化技术转型带来了大量的电子化文档传输需求。文件传输数量呈几何级数增长&#xff0c;传统集中式文件传输模式在爆炸式的增长需求下&#xff0c;银行网点文件下发的效率、可靠性、安全性等方面&#xff0c;都需要重点关…

边缘计算的优势

边缘计算的优势 边缘计算是一种在数据生成地点附近处理数据的技术&#xff0c;而非传统的将数据发送到远端数据中心或云进行处理。这种计算模式对于需要快速响应的场景特别有效&#xff0c;以下详述了边缘计算的核心优势。 1. 降低延迟 边缘计算通过在数据源近处处理数据&…

2款摄像头录像软件,满足你的多种要求!

“有没有一款能够录制摄像头视频的软件呀&#xff1f;我计划录制一些生活小窍门和教学视频&#xff0c;想要能清楚地拍到自己的操作过程。但找了好多软件&#xff0c;都不太满意&#xff0c;真心希望大家能给我推荐几款好用的摄像头录像软件&#xff0c;最好能简单易上手的&…

GPU功能介绍简介

GPU功能介绍简介 随着计算需求的不断升级&#xff0c;尤其是在图形密集型和并行计算任务中&#xff0c;GPU已经从一个简单的图像渲染器件演变成一个强大的计算工具。本篇文章将深入探讨GPU的核心功能、架构以及其在多个领域中的应用。 一、GPU的起源与演进 GPU最初设计用于加速…

百兆集成网络链接器911105A

百兆集成网络链接器&#xff08;有时也称为百兆网卡&#xff09;是一种硬件设备&#xff0c;主要用于计算机与计算机网络之间的高速数据传输。它的主要功能包括&#xff1a; 1. 高速数据传输&#xff1a;百兆集成网络链接器支持100Mbps的数据传输速率&#xff0c;比之前的以太…

抖音老阳讲的选品师项目普通人能赚钱吗?

随着互联网的快速发展&#xff0c;电商行业也迎来了前所未有的繁荣。在这个背景下&#xff0c;选品师这一职业逐渐走进人们的视野。老阳作为行业内的知名人士&#xff0c;经常分享选品师的经验和项目。那么&#xff0c;普通人能否参与老阳讲的选品师项目并且赚钱吗?答案是肯定…

护眼台灯有辐射吗?曝光护眼台灯四大套路!

护眼台灯能够提供便利、健康的光线环境&#xff0c;但作为光学测评师&#xff0c;我观察到一些低品质的护眼台灯存在重大的隐患&#xff0c;这些由劣质材料生产而成的护眼台灯&#xff0c;在使用的过程中&#xff0c;有可能会释放对人体视力有害的辐射&#xff0c;甚至会导致黄…

idea插件快速搜索接口位置之RestfulTool平替Apipost-Helper-2.​0

需求 经常需要根据请求路径搜索某接口位置&#xff0c;特点是接口没有斜杠\&#xff0c;所以双击Shrift找不到接口 RestfulTool 和 RestfulToolkit-fix平替 这两个插件在idea2023.3中无法使用&#xff0c;使用的是Apipost-Helper-2.​0来代替&#xff0c;他也有自己的快捷键…

风险防不胜防?看YashanDB如何守护你的数据库安全(上篇)

数据库作为信息系统的核心&#xff0c;不仅承载着海量的关键数据&#xff0c;还负责向各类用户提供高效、可靠的信息服务&#xff0c;数据库的安全性显得尤为关键&#xff0c;已成为信息安全体系的重中之重。 什么是数据库安全&#xff1f; 数据库安全是数据安全的一个子集&a…

第9章:知识生成提示

知识生成提示&#xff0c;是告诉ChatGPT创造新信息的命令。 你可以告诉它&#xff1a;请生成关于【X】 的新信息。ChatGPT会利用已有知识生成内容。 你也可以同时提出具体要求&#xff0c;如内容类型、长度和风格等。 例1:知识生成 任务: 生成有关特定主题的新信息。指令: 生…

一则 TCP 缓存超负荷导致的 MySQL 连接中断的案例分析

除了 MySQL 本身之外&#xff0c;如何分析定位其他因素的可能性&#xff1f; 作者&#xff1a;龚唐杰&#xff0c;爱可生 DBA 团队成员&#xff0c;主要负责 MySQL 技术支持&#xff0c;擅长 MySQL、PG、国产数据库。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使…

正整数的性质:和与根

目录 数字和 数字和介绍 数字和简单应用 哈沙德数 最小元素各数位之和 数字根 数字根介绍 数字根简单应用 数字和 数字和介绍 简单来说&#xff0c;数字和即一个整数数字每一位数值相加求和所得的值&#xff0c;数字和可以为任意正整数&#xff0c;使用代码获取一个数值的数字和…

干货|交流非线性RCD负载的重要指标

在电力系统中&#xff0c;非线性负载是一个重要的问题。它们会对电力系统的稳定性和电能质量产生重大影响。因此&#xff0c;对非线性负载的研究和管理具有重要的实际意义。在交流非线性RCD&#xff08;Residual Current Device&#xff09;负载中&#xff0c;有几个重要的指标…

挤浆机液压系统比例阀放大器

挤浆机液压系统比例阀放大器是一种在制浆工程中用于洗涤浆料的设备&#xff0c;它通过机械压榨的方式&#xff0c;从纸浆中提取出黑液&#xff08;即造纸过程中产生的废液&#xff09;。主液压系统其主要功能是驱动挤浆机的两个辊子转动。这两个辊子负责将浆料中的水分挤出&…

Unity的旋转实现一些方法总结(案例:通过输入,玩家进行旋转移动)

目录 1. Transform.Rotate 方法 使用 2. Transform.rotation 或 Transform.localRotation 属性与四元数 使用方式&#xff1a; 小案例 &#xff1a;目标旋转角度计算&#xff1a;targetRotation&#xff08;Quaternion类型&#xff09; 玩家发现敌人位置&#xff0c;玩家…