illuminate/database 使用 四

news2024/12/23 16:46:05

文档:Hyperf

Database: Getting Started - Laravel 10.x - The PHP Framework For Web Artisans

因为hyperf使用illuminate/database,所以按照文章,看illuminate/database代码实现。

一、读写分离

根据文档读写的host可以分开。设置读写分离的前提,做数据库出从同步。
 

1.1 数据库主从同步

参考:mysql5.7 主从配置-CSDN博客

1.2 设置

配置中设置三个数据read、write、sticky。read、write都包含host数组,其配置会和主要配置合并。就是说,比如host相同,应该在read、write中设置对应数据,以覆盖主要设置。

sticky选项是一个可选值,可用于允许在当前请求周期内立即读取已写入数据库的记录。如果启用了sticky选项,并且在当前请求周期中对数据库执行了“写”操作,则任何进一步的“读”操作都将使用“写”连接。这确保了在请求周期内写入的任何数据都可以在同一请求期间立即从数据库中读回。

源码如下:

#Illuminate\Database\Connectors\ConnectionFactory
protected function getReadConfig(array $config)
    {
        return $this->mergeReadWriteConfig(
            $config, $this->getReadWriteConfig($config, 'read')
        );
    }
protected function getWriteConfig(array $config)
    {
        return $this->mergeReadWriteConfig(
            $config, $this->getReadWriteConfig($config, 'write')
        );
    }
protected function mergeReadWriteConfig(array $config, array $merge)
    {
        return Arr::except(array_merge($config, $merge), ['read', 'write']);
    }


#Illuminate\Database\Connection
public function getReadPdo()
    {
        if ($this->transactions > 0) {
            return $this->getPdo();
        }

        if ($this->readOnWriteConnection ||
            ($this->recordsModified && $this->getConfig('sticky'))) {
            return $this->getPdo();
        }

        if ($this->readPdo instanceof Closure) {
            return $this->readPdo = call_user_func($this->readPdo);
        }

        return $this->readPdo ?: $this->getPdo();
    }

1.3 测试

配置如下

#config/database.php
return [
    'migrations' => '', //数据迁移
    //PDO文档 https://www.php.net/manual/zh/pdo.constants.php
    'default' => 'master',
    'connections' => [
        'master' => [
            'driver' => 'mysql',
            'host' => 'localhost',
            'database' => 'test',
            'username' => 'root',
            'password' => 'qwe110110',
            'charset' => 'utf8',
            'collation' => 'utf8_general_ci',
            'prefix' => '',
            'port' => '3306',
            'read' => [
                'host' => ['127.0.0.1'],
                'port' => '3307',
            ],
            'write' => [
                'host' => ['127.0.0.1'],
                'port' => '3306',
            ],
        ],
    ]
];

 测试代码

function test1()
{
    new App();
    $query = "concat('-',id)";
    $as = "id";
    //$info1 = DbManager::table('userinfo')->select(['name'])->selectSub($query, $as)->addSelect(['age'])->get();
    $info1 = DbManager::table('userinfo')->select(['name'])->selectSub($query, $as)->addSelect(['age'])->get();
    var_dump($info1);
    $data = $info1->all();
    $insertData = ['name' => 'test1', 'age' => 1];
    $id = DbManager::table('userinfo')->insertGetId($insertData);
    var_dump($id);
    //exit;
    //$sql = "CONCAT('A-',name)";
    //$info2 = DbManager::table('userinfo')->selectSub($sql, "table")->toSql()->dump();
}
test1();

 返回结果

string(29) "Illuminate\Support\Collection"
array(8) {
  [0] =>
  class stdClass#18 (3) {
    public $name =>
    string(3) "123"
    public $id =>
    string(2) "-1"
    public $age =>
    int(22)
  }
  [1] =>
  class stdClass#22 (3) {
    public $name =>
    string(5) "name2"
    public $id =>
    string(2) "-2"
    public $age =>
    int(13)
  }
  [2] =>
  class stdClass#23 (3) {
    public $name =>
    string(5) "name3"
    public $id =>
    string(2) "-3"
    public $age =>
    int(24)
  }
  [3] =>
  class stdClass#24 (3) {
    public $name =>
    string(5) "33321"
    public $id =>
    string(2) "-4"
    public $age =>
    int(0)
  }
  [4] =>
  class stdClass#25 (3) {
    public $name =>
    string(5) "test1"
    public $id =>
    string(2) "-5"
    public $age =>
    int(1)
  }
  [5] =>
  class stdClass#26 (3) {
    public $name =>
    string(5) "test1"
    public $id =>
    string(2) "-6"
    public $age =>
    int(1)
  }
  [6] =>
  class stdClass#27 (3) {
    public $name =>
    string(5) "test1"
    public $id =>
    string(2) "-7"
    public $age =>
    int(1)
  }
  [7] =>
  class stdClass#28 (3) {
    public $name =>
    string(5) "test1"
    public $id =>
    string(2) "-8"
    public $age =>
    int(1)
  }
}
int(9)

 从库:

 主库

 

 测试成功~

1.4 返回数据处理

从测试结果看,返回的都是对象,因为默认使用PDO::FETCH_OBJ。

参考:PHP: PDO - Manual

源码如下

#Illuminate\Database\Capsule\Manager
public function __construct(Container $container = null)
    {
        $this->setupContainer($container ?: new Container);

        // Once we have the container setup, we will setup the default configuration
        // options in the container "config" binding. This will make the database
        // manager work correctly out of the box without extreme configuration.
        $this->setupDefaultConfiguration();

        $this->setupManager();
    }
protected function setupDefaultConfiguration()
    {
        $this->container['config']['database.fetch'] = PDO::FETCH_OBJ;

        $this->container['config']['database.default'] = 'default';
    }
public function setFetchMode($fetchMode)
    {
        $this->container['config']['database.fetch'] = $fetchMode;

        return $this;
    }

#Illuminate\Database\Connection
protected $fetchMode = PDO::FETCH_OBJ;
public function select($query, $bindings = [], $useReadPdo = true)
    {
        return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
            if ($this->pretending()) {
                return [];
            }

            // For select statements, we'll simply execute the query and return an array
            // of the database result set. Each element in the array will be a single
            // row from the database table, and will either be an array or objects.
            $statement = $this->prepared(
                $this->getPdoForSelect($useReadPdo)->prepare($query)
            );

            $this->bindValues($statement, $this->prepareBindings($bindings));

            $statement->execute();

            return $statement->fetchAll();
        });
    }
protected function prepared(PDOStatement $statement)
    {
        $statement->setFetchMode($this->fetchMode);

        $this->event(new StatementPrepared(
            $this, $statement
        ));

        return $statement;
    }

想返回数组可以设置为PDO::FETCH_ASSOC。最简单的方法就是替换源码,二次开发最好就是用对象,或者写个对象转数组的方法,tp里面有源码。tp是查出来对象,可使用toArray()搞成数组。

get()返回的类是Illuminate\Support\Collection,此类中还有一些数据统计的方法,比如平均值之类。意思就是查出来数据再做数据统计。

二、多库配置

根据laravel文档:如果应用程序在config/database.php配置文件中定义了多个连接,则可以通过DB facade提供的连接方法访问每个连接。

use Illuminate\Support\Facades\DB;
 
$users = DB::connection('sqlite')->select(/* ... */);
$pdo = DB::connection()->getPdo();

但是仅用这个库由于没有对应数据,会返回db类是null。

源码如下:

#Illuminate\Support\Facades\Facade
public static function getFacadeRoot()
    {
        return static::resolveFacadeInstance(static::getFacadeAccessor());
    }
public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();
        if (!$instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        return $instance->$method(...$args);
    }
 protected static function resolveFacadeInstance($name)
    {
        if (is_object($name)) {
            return $name;
        }

        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }
        if (static::$app) {
            return static::$resolvedInstance[$name] = static::$app[$name];
        }
    }

根据方法resolveFacadeInstance(),$name应该是‘db’,不是对象,$resolvedInstance、$app没有对应对象,所以返回空。估计得配合其他类库。比如hyperf中需要

composer require hyperf/database

 那么不用其他类库怎么实现多库切换……

多库配置

return [
    'migrations' => '', //数据迁移
    //PDO文档 https://www.php.net/manual/zh/pdo.constants.php
    'default' => 'master',
    'connections' => [
        'master' => [
            'driver' => 'mysql',
            'host' => 'localhost',
            'database' => 'test',
            'username' => 'root',
            'password' => 'mima',
            'charset' => 'utf8',
            'collation' => 'utf8_general_ci',
            'prefix' => '',
            'port' => '3306',
            'read' => [
                'host' => ['127.0.0.1'],
                'port' => '3307',
            ],
            'write' => [
                'host' => ['127.0.0.1'],
                'port' => '3306',
            ],
        ],
        'test' => [
            "driver" => "mysql",
            "host" => "127.0.0.1",
            "database" => "test1",
            "username" => "root",
            "password" => "mima",
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'port' => '3307',
        ],
    ],
];
function test2()
{
    $app = new App();
    $info = DbManager::connection('test')->table('userinfo')->where('id', '=', 1)->get();
    $info = $info->first();
    var_dump($info);
}

test2();

 返回数据

class stdClass#20 (2) {
  public $id =>
  int(1)
  public $name =>
  string(1) "1"
}

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

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

相关文章

【ChatGLM2-6B】Docker下部署及微调

【ChatGLM2-6B】小白入门及Docker下部署 一、简介1、ChatGLM2是什么2、组成部分3、相关地址 二、基于Docker安装部署1、前提2、CentOS7安装NVIDIA显卡驱动1)查看服务器版本及显卡信息2)相关依赖安装3)显卡驱动安装 2、 CentOS7安装NVIDIA-Doc…

Python live-server安装使用

live-server是一个具有实时加载功能的小型服务器,可以使用它来破解html/css/javascript,但是不能用于部署最终站点。也就是说我们可以在项目中实时用live-server作为一个实时服务器实时查看开发的网页或项目效果。(1) 安装live-server npm in…

MySQL 批量插入记录报 Error 1390 (HY000)

文章目录 1.背景2.问题3.分批插入4.一次最多能插入多少条记录?参考文献 1.背景 Golang 后台服务使用 GORM 实现与 MySQL 的交互,在实现一个通过 Excel 导入数据的接口时,使用 Save 方法一次性插入大量记录(>1w)时报…

【机器学习】聚类(二):原型聚类:LVQ聚类(学习向量量化)

文章目录 一、实验介绍1. 算法流程2. 算法解释3. 算法特点4. 应用场景5. 注意事项 二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 导入必要的库1. LVQ类a. 构造函数b. 闵可夫斯基距离c. LVQ聚类过程e. 聚类结果可视化 2. 辅助函数3. 主函数a. 命令行界面 &#xff…

Diffusion Model: DDIM

本文相关内容只记录看论文过程中一些难点问题,内容间逻辑性不强,甚至有点混乱,因此只作为本人“备忘”,不建议其他人阅读。 DENOISING DIFFUSION IMPLICIT MODELS: https://arxiv.org/abs/2010.02502 前序知识 DDPM:…

装饰者设计模式

package com.jmj.pattern.decorator;/*** 快餐类(抽象构建角色)*/ public abstract class FastFood {private float price;private String desc;public float getPrice() {return price;}public void setPrice(float price) {this.price price;}public String getDesc() {retu…

机器学习之自监督学习(五)MAE翻译与总结(二)

参考:Self-Supervised Learning 超详细解读 (六):MAE:通向 CV 大模型 - 知乎 (zhihu.com) 仅供个人学习使用,侵权私信删。 自监督学习:MAE.. 1 1.1 self-supervised learning.. 1 1.2 Masked Autoencoders&#xff…

【C】内存函数

目录 1. memcpy 使用和模拟实现 2. memmove 使⽤和模拟实现 3. memset 函数的使用 4. memcmp 函数的使用 1. memcpy 使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数memcpy从source的位置开始向后复制num个字节的数据到d…

某图app sig、client_session

文章目录 声明目标加密参数定位代码实现声明 本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请私信我立即删除! 目标 这次看一下某图秀秀app 搜索接口: 抓一下包 url参数提取 url = "https://api.x…

springboot项目同时启动web服务和grpc服务

springboot项目同时启动web服务和grpc服务 一. 创建项目二. 引入依赖三. 测试3.1 http服务3.2 grpc服务 四. 整体代码结构 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 一. 创建…

推荐几个比较给力的网站,看看有没有你喜欢的

1、电子书大全 Loading...免翻墙 消除背景 在线抠图软件_图片去除背景 | remove.bg – remove.bg 临时邮箱 http://linshiyouxiang.net/ 在线短信验证码接收码平台 https://www.yinsiduanxin.com/ 图片放大无损失 waifu2x小翻墙 AI 人工智能图片放大 Bigjpg - AI Su…

【Spring源码】Spring Event事件

目录 1、前言 2、什么是Spring Event? 3、基本使用 3.1、定义事件 3.2、发布事件 3.3、监听事件 3.3.1、继承ApplicationListener 3.3.2、使用EventListener注解 4、Spring Event是同步还是异步? 4.1、源码实现 4.2、如何实现异步 4.2.1、使用…

什么是 Jest ? Vue2 如何使用 Jest 进行单元测试?Vue2 使用 Jest 开发单元测试实例

什么是Jest? Jest 是一个流行的 JavaScript 测试框架,由 Facebook 开发并维护,专注于简单性和速度。它通常用于编写 JavaScript 和 TypeScript 应用程序的单元测试、集成测试和端到端测试。 特点: 简单易用: Jest 提供简洁的 API 和易于理解的语法,使得编写测试用例变得…

【Android Gradle】之Gradle入门及 wrapper 生成(一)

😄作者简介: 小曾同学.com,一个致力于测试开发的博主⛽️,主要职责:测试开发、CI/CD 如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。 😊 座右铭:不…

大中小协作 共筑科学梦——华中科技大学附属花城中学举办首届科技节

为普及科学知识,张扬科学精神,创设浓郁的科学氛围,11月24日,华中科技大学附属花城中学举办了以“走近科学,触碰未来”为主题的首届科技节暨科创文化展示周活动。学生们在学习中感受科技的魅力,在“玩”中感…

Vue新手必学:Vue的使用和Vue脚手架详解

文章目录 引言第一部分:Vue的基本使用1.1 安装Vue1.2 创建Vue项目1.3 编写第一个Vue组件1.4 在主页面中使用组件1.5 运行Vue项目 第二部分:Vue脚手架的使用2.1 Vue脚手架是什么2.2 创建Vue项目2.3 项目结构2.4 运行项目2.5 插件和配置 第三部分&#xff…

2023年汉字小达人市级比赛在线模拟题的使用顺序、建议和常见问题

今天是2023年11月25日,星期六,上午举办了2023年第八届上海小学生古诗文大会的复选活动(复赛),结束了复选活动,很多学霸孩子们马上就开始投入到第十届汉字小达人的市级活动(市级比赛)…

使用 PyODPS 采集神策事件数据

文章目录 一、前言二、数据采集、处理和入库2.1 获取神策 token2.2 请求神策数据2.3 数据处理-面向数组2.4 测试阿里云 DataFrame 入库2.5 调度设计与配置2.6 项目代码整合 三、小结四、花絮-避坑指南第一坑:阿里云仅深圳节点支持神策数据第二坑:神策 To…

小米AI布局的三大亮点:财报数据、高层视野、未来想象

小米作为一家以互联网为核心的智能终端和生态链公司,一直在不断探索人工智能(AI)的应用和创新。在最近公布的2023年第三季度财报中,小米透露了一些关于AI业务的重要信息,展现了其在AI领域的核心业务和竞争优势&#xf…

github上不去

想要网上找代码发现github上不去了 发现之前的fastgit也用不了了 搜了很多地方终于找到了 记录保存一下 fastgithub最新下载 选择第二个下载解压就行 使用成功!