hyperf 十八 数据库 一

教程地址:Hyperf

一、安装

1.1 hyperf框架

composer require hyperf/db-connection

1.2 其他框架

composer require hyperf/database

二、配置

配置项类型默认值备注
driverstring数据库引擎
hoststring数据库地址
databasestring数据库默认 DB
usernamestring数据库用户名
passwordstringnull数据库密码
charsetstringutf8数据库编码
collationstringutf8_unicode_ci数据库编码
prefixstring''数据库模型前缀
timezonestringnull数据库时区
pool.min_connectionsint1连接池内最少连接数
pool.max_connectionsint10连接池内最大连接数
pool.connect_timeoutfloat10.0连接等待超时时间
pool.wait_timeoutfloat3.0超时时间
pool.heartbeatint-1心跳
pool.max_idle_timefloat60.0最大闲置时间
optionsarrayPDO 配置

 options相关pdo文档:PHP: PDO - Manual

三、多库配置、读写分离、原生查询、sql输出

 由于hyperf/database 衍生于 illuminate/database

illuminate/database多库配置和读写分离参考illuminate/database 使用 四-CSDN博客  ;原生查询和sql输出参考illuminate/database 使用 五-CSDN博客

3.1 原生查询-事务

3.1.1 自动管理数据库事务

                根据文档描述:如果事务的闭包 Closure 中出现一个异常,事务将会回滚。如果事务闭包 Closure 执行成功,事务将自动提交。

                确实比手动方便,但是还得查下报错怎么处理。

                根据之前文章,应该明白Illuminate\Database中调用顺序,即从Illuminate\Database\Capsule\Manager最后会调用到Illuminate\Database\Connectionl。Connectionl中调用Concerns\ManagesTransactions类。transaction()方法在ManagesTransactions类中被调用。

                源码如下

trait ManagesTransactions
{
    /**
     * Execute a Closure within a transaction.
     *
     * @param  \Closure  $callback
     * @param  int  $attempts
     * @return mixed
     *
     * @throws \Throwable
     */
    public function transaction(Closure $callback, $attempts = 1)
    {
        for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
            $this->beginTransaction();

            // We'll simply execute the given callback within a try / catch block and if we
            // catch any exception we can rollback this transaction so that none of this
            // gets actually persisted to a database or stored in a permanent fashion.
            try {
                $callbackResult = $callback($this);
            }

            // If we catch an exception we'll rollback this transaction and try again if we
            // are not out of attempts. If we are out of attempts we will just throw the
            // exception back out and let the developer handle an uncaught exceptions.
            catch (Throwable $e) {
                $this->handleTransactionException(
                    $e, $currentAttempt, $attempts
                );

                continue;
            }

            try {
                if ($this->transactions == 1) {
                    $this->getPdo()->commit();
                }

                $this->transactions = max(0, $this->transactions - 1);

                if ($this->transactions == 0) {
                    optional($this->transactionsManager)->commit($this->getName());
                }
            } catch (Throwable $e) {
                $this->handleCommitTransactionException(
                    $e, $currentAttempt, $attempts
                );

                continue;
            }

            $this->fireConnectionEvent('committed');

            return $callbackResult;
        }
    }
    /**
     * Handle an exception encountered when running a transacted statement.
     *
     * @param  \Throwable  $e
     * @param  int  $currentAttempt
     * @param  int  $maxAttempts
     * @return void
     *
     * @throws \Throwable
     */
    protected function handleTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
    {
        // On a deadlock, MySQL rolls back the entire transaction so we can't just
        // retry the query. We have to throw this exception all the way out and
        // let the developer handle it in another way. We will decrement too.
        if ($this->causedByConcurrencyError($e) &&
            $this->transactions > 1) {
            $this->transactions--;

            optional($this->transactionsManager)->rollback(
                $this->getName(), $this->transactions
            );

            throw $e;
        }

        // If there was an exception we will rollback this transaction and then we
        // can check if we have exceeded the maximum attempt count for this and
        // if we haven't we will return and try this query again in our loop.
        $this->rollBack();

        if ($this->causedByConcurrencyError($e) &&
            $currentAttempt < $maxAttempts) {
            return;
        }

        throw $e;
    }
/**
     * Handle an exception encountered when committing a transaction.
     *
     * @param  \Throwable  $e
     * @param  int  $currentAttempt
     * @param  int  $maxAttempts
     * @return void
     *
     * @throws \Throwable
     */
    protected function handleCommitTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
    {
        $this->transactions = max(0, $this->transactions - 1);

        if ($this->causedByConcurrencyError($e) &&
            $currentAttempt < $maxAttempts) {
            return;
        }

        if ($this->causedByLostConnection($e)) {
            $this->transactions = 0;
        }

        throw $e;
    }
    ……
}

如源码所示,闭包执行错误,执行handleTransactionException()方法,处理回滚,并抛出异常。

$this->transactions--大概是处理事务嵌套相关代码。

提交异常,执行handleCommitTransactionException()方法,嵌套事务大概会继续执行,最后抛出异常。

测试代码

function test4()
{
    Capsule::transaction(function () {
        Capsule::table('userinfo')->where(['id' => 1])->update(['votes' => 1]);
    });
}
test4();

 运行结果

Fatal error: Uncaught PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'votes' in 'field list' in D:\workspace\php\wj_test\illuminate_database\vendor\illuminate\database\Connection.php on line 712

Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'votes' in 'field list' (SQL: update `userinfo` set `votes` = 1 where (`id` = 1)) in D:\workspace\php\wj_test\illuminate_database\vendor\illuminate\database\Connection.php on line 712

Call Stack:
    0.0009     411368   1. {main}() D:\workspace\php\wj_test\illuminate_database\test.php:0
    0.0208    1925160   2. test4() D:\workspace\php\wj_test\illuminate_database\test.php:119
    0.0208    1925480   3. Illuminate\Database\Capsule\Manager::transaction(class Closure) D:\workspace\php\wj_test\illuminate_database\test.php:117
    0.0208    1925856   4. Illuminate\Database\Capsule\Manager::__callStatic(string(11), array(1)) D:\workspace\php\wj_test\illuminate_database\test.php:117
    0.0269    2634512   5. Illuminate\Database\MySqlConnection->transaction(class Closure, ???) D:\workspace\php\wj_test\illuminate_database\vendor\illuminate\database\Capsule\Manager.php:200
    0.0705    3895296   6. Illuminate\Database\MySqlConnection->handleTransactionException(class Illuminate\Database\QueryException, long, long) D:\workspace\php\wj_test\illuminate_database\vendor\illuminate\database\Concerns\ManagesTransactions.php:37

此时update执行Illuminate\Database\Connection::update(),update调用Connection::run()执行,run()通过Connection::runQueryCallback()执行,产生PDO异常,再将PDO异常传递给\Illuminate\Database\QueryException异常。

使用throw 会直接输出异常。

PDOException:PHP: PDOException - Manual

3.1.2 手动管理数据库事务

function test5()
{
    Capsule::beginTransaction();
    try {
        Capsule::table('userinfo')->where(['id' => 1])->update(['votes' => 1]);
        Capsule::commit();
    } catch (\Throwable $th) {
        var_dump($th->getMessage());
        Capsule::rollBack();
    }
}
test5();

 和之前是同样的道理,代码最后执行都是Connectionl类,Connectionl::beginTransaction()、Connectionl::commit()、Connectionl::rollback(),都是Connectionl中调用的ManagesTransactions类中的方法。

例子中Capsule类相当于官网的DB类。

四、构造器

参考

illuminate/database 使用 一-CSDN博客

Hyperf

自己写的博客有涉及一些运行原理,官网的例子比较多。

 

  • 20
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Hyperf 是一个基于 PHP 的高性能微服务框架,它是由 Hyperf 开发团队基于 Swoole 扩展开发的。Hyperf 框架具有轻量级、高性能、灵活可扩展等特点,适用于构建各种类型的微服务应用。 以下是 Hyperf 微服务框架的一些特点和功能: 1. 高性能:Hyperf 基于 Swoole 扩展,充分利用了 Swoole 的协程特性和异步非阻塞的 IO 模型,提供了卓越的性能表现。 2. 轻量级:Hyperf 框架本身非常轻量级,核心代码量少,运行时内存占用低,可以快速启动和运行。 3. 灵活可扩展:Hyperf 提供了丰富的组件和扩展机制,可以根据项目需求进行灵活的定制和扩展。 4. 支持多种协议:Hyperf 支持 HTTP、WebSocket、TCP、UDP 等多种协议,可以满足不同类型的微服务应用需求。 5. 强大的依赖注入容器:Hyperf 内置了一个强大的依赖注入容器,可以方便地管理和注入各种组件和服务。 6. 高度可测试性:Hyperf 提供了丰富的测试工具和测试支持,可以方便地进行单元测试和集成测试。 7. 支持分布式部署:Hyperf 支持分布式部署,可以通过配置中心、服务注册与发现等机制实现微服务的高可用和负载均衡。 8. 提供丰富的组件:Hyperf 提供了许多常用的组件,如数据库 ORM、缓存、消息队列、验证器等,可以快速开发各种类型的微服务应用。 总之,Hyperf 是一个功能强大、性能优越的 PHP 微服务框架,适用于构建高性能、可扩展的微服务应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lsswear

感谢大佬打赏 q(≧▽≦q)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值