hyperf 二十五 数据迁移 一

教程:Hyperf

版本说明

一 生成迁移

php bin/hyperf.php gen:migration create_users_table

执行文件:Hyperf\Database\Commands\Migrations\GenMigrateCommand

功能:创建迁移文件

参数:

  1. name  文件名称

选项:

  1. create 创建。设置create未设置table,则create的值设置给table,其值重新赋值为true。

  2. table 表名。table未设置,则根据参数name文件名正则出表名。

  3. path 路径

  4. realpath 绝对路径

参数通过Hyperf\Database\Commands\Migrations\GenMigrateCommand::getArguments()设置,选项通过Hyperf\Database\Commands\Migrations\GenMigrateCommand::getOptions()设置。

文件创建通过调用Hyperf\Database\Migrations\MigrationCreator::create()实现。

若根据name转化出的类名对应的类存在会抛出错误,类似于"[ERROR] Created Migration: A CreateUserinfoTable class already exists."。

若table为空,则Stub文件为blank.stub;create为true,stub文件为create.stub,否则为update.stub。这些stub文件均为系统的模板文件,存放于vendor\hyperf\database\src\Migrations\stubs。

stub文件用于字符串替换。最后会将替换后的字符串写入path对应的文件,文件名为name。

二 迁移结构

生成的迁移文件\migrations\2024_03_02_034344_create_userinfo_table.php,中包括up()和down()两个方法。up()用于添加新的数据表,字段或者索引到数据库。down()反之用于回滚。

2.1 up

通过 Hyperf\Database\Schema\Schema::__callStatic()获取链接对象。

Schema::__callStatic()调用ConnectionResolver::connection()。connection()参数为空,则使用default数据库链接,否则从加载的配置文件信息读取对应的数据库链接信息。

源码中,数据库连接使用default。

ConnectionResolver::connection()调用Hyperf\Pool\Pool::get()中通过Hyperf\DbConnection\Pool\DbPool::createConnection()创建的Hyperf\DbConnection\Connection类实体对象。

Hyperf\DbConnection\Connection::__construct()根据配置获取链接,比如mysql驱动使用Hyperf\Database\MySqlConnection。MySqlConnection父类为Hyperf\Database\Connection。

所以Schema::__callStatic()最后调用Hyperf\Database\Connection::getSchemaBuilder()或其子类的getSchemaBuilder()方法,返回的Hyperf\Database\Schema\Builder类实体对象。

所以Schema::create(),就是调用Hyperf\Database\Schema\Builder::create()。Builder::create()调用Hyperf\Database\Schema\Blueprint::build()。

还是以mysql驱动为例,设置默认grammar为Hyperf\Database\Schema\Grammars\MySqlGrammar。Blueprint::build()中使用MySqlGrammar::compileCreate()生成对应命令的sql字符串,再通过Hyperf\Database\Connection::statement()执行。

根据源码,Hyperf\Database\Schema\Schema::__callStatic()应该是执行Hyperf\Database\Schema\Blueprint的方法。

2.2 down

根据up()的逻辑,down实际执行Schema::dropIfExists(),即为执行Hyperf\Database\Schema\Blueprint::dropIfExists()。使用mysql驱动,会执行Hyperf\Database\Schema\Grammars\MySqlGrammar::compileDropIfExists()。

三 运行迁移

运行命令

php bin/hyperf.php migrate

没有参数,只有选项。

选项:

  1. database 设置链接使用的数据库

  2. seed 指示是否应该重新运行种子任务
  3. force 在生产环境中强制运行该操作

根据database获取数据库链接,默认default,为配置D:\config\autoload\databases.php文件中数组最外层的key值。根据其获取数据库连接的配置信息。根据对应链接类比如Hyperf\Database\MySqlConnection,其中的getSchemaBuilder()方法获取的Hyperf\Database\Schema\MySqlBuilder类的实体对象,执行MySqlBuilder::hasTable()判断表是否存在。

可能是源码版本的问题,没找到用户设定的force使用代码。

使用seed参数执行db:seed命令,其命令参数--force设置为true,用于填充数据。执行Hyperf\Database\Commands\Seeders\SeedCommand::handle()。可能需要先运行gen:seeder,执行Hyperf\Database\Commands\Seeders\GenSeederCommand::handle()。根据vendor\hyperf\database\src\Seeders\stubs文件生成种子文件,用于SeedCommand::handle()中执行。

3.1 强制执行

php bin/hyperf.php migrate --force

3.2 回滚迁移

3.2.1 回滚指定迁移

php bin/hyperf.php migrate:rollback

选项:

  1. database 设置链接使用的数据库
  2. pretend  转储将要运行的SQL查询

  3. step 执行步数

执行文件Hyperf\Database\Commands\Migrations\RollbackCommand,RollbackCommand::handle()运行Hyperf\Database\Migrations\Migrator::rollback()。

Migrations\Migrator::rollback()使用参数step。step参数意味着回滚的步数,需要配合数据库记录回滚的操作,通过使用step作为limit参数创建sql语句,返回批次号列表。未设置step参数返回最有一次迁移的批次号。

Migrator::rollback()实际运行迁移结构中的down(),最后删除管理迁移记录表中的对应数据。

3.2.2 回滚所有迁移

php bin/hyperf.php migrate:reset

选项:

  1. database 设置链接使用的数据库
  2. pretend  转储将要运行的SQL查询

执行文件Hyperf\Database\Commands\Migrations\ResetCommand,运行Hyperf\Database\Migrations\Migrator::reset()。

Migrator::reset()和Migrator::rollback()不同,获取批次号从大到小排列的全部数据。便利数据时运行down()。但是没有管理迁移记录表数据的删除操作。

3.3 回滚并迁移

php bin/hyperf.php migrate:refresh

选项:

  1. database 设置链接使用的数据库
  2. pretend  转储将要运行的SQL查询

  3. force 在生产环境中强制运行该操作

  4. path 路径

  5. realpath 绝对路径

  6. seed 指示是否应该重新运行种子任务

  7. seeder 设置种子的类名

  8. step 执行步数

执行文件Hyperf\Database\Commands\Migrations\RefreshCommand。step大于0执行migrate:rollback,否则执行migrate:reset,最后执行migrate。设置seed或seeder后执行db:seed。

选项的使用参数其他命令。其设置的选项也是在其他命令中运行。其本身没有其他逻辑。

3.4 重建数据库

php bin/hyperf.php migrate:fresh

选项:

  1. database 设置链接使用的数据库
  2. drop-views 删除所有视图

  3. path  路径

  4. realpath 绝对路径

  5. force 在生产环境中强制运行该操作

  6. step 执行步数

  7. seed 指示是否应该重新运行种子任务

  8. seeder 设置种子的类名

执行文件Hyperf\Database\Commands\Migrations\FreshCommand。

drop-views为true则删除视图,以myql驱动为例,执行Hyperf\Database\Schema\MySqlBuilder::dropAllViews(),MySqlBuilder::dropAllViews()调用Hyperf\Database\Schema\Grammars\MySqlGrammar::compileDropAllViews()返回的sql字符串,在Hyperf\Database\MySqlConnection的父类Hyperf\Database\Connection::statement()中执行。

四 测试

show databases;
use test1;
show tables;

 运行结果

#show databases;
test
test1
#show tables;
null

 证明test1数据库中无表。

数据库链接配置文件

#config\autoload\databases.phpdeclare (strict_types = 1);
/*** This file is part of Hyperf.** @link     https://www.hyperf.io* @document https://hyperf.wiki* @contact  group@hyperf.io* @license  https://github.com/hyperf/hyperf/blob/master/LICENSE*/
return ['default' => ['driver' => env('DB_DRIVER', 'mysql'),'host' => env('DB_HOST', '127.0.0.1'),'database' => env('DB_DATABASE', 'test'),'port' => env('DB_PORT', 3306),'username' => env('DB_USERNAME', 'root'),'password' => env('DB_PASSWORD', 'root'),'charset' => env('DB_CHARSET', 'utf8'),'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),'prefix' => env('DB_PREFIX', ''),],'default2' => ['driver' => env('DB_DRIVER', 'mysql'),'host' => '127.0.0.1','database' => 'test1','port' => env('DB_PORT', 3306),'username' => env('DB_USERNAME', 'root'),'password' => env('DB_PASSWORD', 'root'),'charset' => env('DB_CHARSET', 'utf8'),'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),'prefix' => env('DB_PREFIX', ''),],
];

使用env文件会先取env文件的值,所以在env有值的情况下设置的自定值无效。即env("DB_DATABASE",'test')和env("DB_DATABASE",'test1')值相同,都是env文件DB_DATABASE的值。

执行命令

php bin/hyperf.php gen:migration create_userinfo_table

 生成文件migrations\2024_03_02_034344_create_userinfo_table.php

 php bin/hyperf.php migrate --database=default2 --pretend
#show tables;
migrations
userinfo
#show CREATE table migrations;
CREATE TABLE `migrations` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`migration` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,`batch` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

此时俩表都没有数据。添加字段之后,应该也是仅适合表结构迁移。

表数据迁移可以使用工具或者sql文件执行。

为测试回滚等操作,生成新的迁移文件。

php bin/hyperf.php gen:migration create_userinfo2_table --table=userinfo
php bin/hyperf.php gen:migration create_userinfo3_table --create=userinfo

 在对应表迁移文件已有的基础上,检查类名已存在会报错。判断类名已存之前未判断--create和--table参数,所以设置这俩不会解决报错,除非换路径或把想同的类名改掉。

使用table生成的文件如下

class CreateUserinfo2Table extends Migration
{/*** Run the migrations.*/public function up(): void{Schema::table('userinfo', function (Blueprint $table) {//});}/*** Reverse the migrations.*/public function down(): void{Schema::table('userinfo', function (Blueprint $table) {//});}
}

使用create生成文件如下

class CreateUserinfo3Table extends Migration
{/*** Run the migrations.*/public function up(): void{Schema::create('userinfo', function (Blueprint $table) {$table->bigIncrements('id');$table->timestamps();});}/*** Reverse the migrations.*/public function down(): void{Schema::dropIfExists('userinfo');}
}

 migrations表没数据,回滚会报错"Nothing to rollback."。所以需要看下migrations表何时写入数据。经过查询发现,应该是pretend选项导致。源码执行up()之后,判断pretend参数,为true则执行Hyperf\Database\Migrations\Migrator::pretendToRun(),然后return。pretend默认为false,最后执行Hyperf\Database\Migrations\DatabaseMigrationRepository::log(),写入migrations表。

删表重来一次。

DROP TABLE migrations;
DROP TABLE userinfo;
php bin/hyperf.php migrate --database=default2

 会在test1数据库没有userinfo表存在的情况下,报数据表userinfo重复,因为test数据库有userinfo。这个报错还是执行create后报的错,应为create执行在test数据库中。

但是加选项pretend执行Hyperf\Database\Migrations\Migrator::pretendToRun(),就可以正常执行。

由于测试环境为,一个项目使用两个数据库连接配置链接本地两个库,而不使用pretend的情况下迁移文件默认使用default。即使用同一个项目环境迁移数据库必须使用prepend,但是迁移后的库就记录不了迁移记录。

可以稍微改下

#Hyperf\Database\Migrations\Migratorprotected function runMigration(object $migration, string $method): void {……$this->resolver->setDefaultConnection($migration->getConnection() ?: $this->connection);……
}#改为
protected function runMigration(object $migration, string $method): void {……$this->resolver->setDefaultConnection($this->connection ?: $migration->getConnection());……
}

归结原因是按照之前逻辑获取迁移文件对象的getConnection()方法,因为是新对象获取的就是default。所以应该改为先判断当前对象的connect属性是否有值,没有则采用新对象的默认值。

执行

 php bin/hyperf.php migrate --database=default2

成功

Migrating: 2024_03_06_082623_create_userinfo_table
Migrated:  2024_03_06_082623_create_userinfo_table

此时migrations表中数据正常。

select * from migrations

 

执行回滚

php bin/hyperf.php migrate:rollback --database=default2

成功

Rolling back: 2024_03_06_082623_create_userinfo_table
Rolled back:  2024_03_06_082623_create_userinfo_table

此时 migragtions没有数据,test1库中没有userinfo表。

五 源码修改内容

#Hyperf\Database\Migrations\Migratorprotected function runMigration(object $migration, string $method): void {……$this->resolver->setDefaultConnection($migration->getConnection() ?: $this->connection);……
}#改为
protected function runMigration(object $migration, string $method): void {……$this->resolver->setDefaultConnection($this->connection ?: $migration->getConnection());……
}

 修改原因:执行时使用新对象默认的数据库链接(default),不能使用自定义的数据库链接。

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

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

相关文章

Rust 安装与版本更新

Rust 简介 Rust ,一门赋予每个人构建可靠且高效软件能力的语言,主打内存安全。 2024年2月,在一份 19 页的报告《回归基础构件:通往安全软件之路》中,白宫国家网络主任办公室(ONCD)呼吁开发者使…

NoSQL--3.MongoDB配置(Linux版)

目录 2.2 Linux环境下操作 2.2.1 传输MongoDB压缩包到虚拟机: 2.2.2 启动MongoDB服务: 2.2 Linux环境下操作 2.2.1 传输MongoDB压缩包到虚拟机: (笔者使用XShell传输) 如果不想放在如图的路径,删除操作…

Appium系列(1)安装启动Appium

Appium环境准备 Mac电脑jdk环境AndroidSDK环境node>8.1.0(最好用最新版本) 安装命令 npm i -g appium安装不成功请检查node 版本是否正确 安装成功命令行输入appium回车查看 安装驱动程序 1、先检查当前驱动情况 通过 appium driver list 进行…

RK356X RK3588 单独编译kernel 与烧录

RK356X RK3588 单独编译kernel 与烧录 可以快速提高我们开发与调试速度 网上可查到的方法如下: RK3568 Android12: 1.添加kernel-4.19/makekernel.sh #!/bin/sh make -j24 ARCHarm64 CC../prebuilts/clang/host/linux-x86/clang-r416183b/bin/clang …

RF接口测试(1)

RF是做接口测试的一个非常方便的工具,我们只需要写好发送报文的脚本,就可以灵活的对接口进行测试。 做接口测试我们需要做如下工作: 1、拼接发送的报文 2、发送请求的方法 3、对结果进行判断 我们先按步骤实现,再进行RF操作的…

比较 2 名无人机驾驶员:借助分析飞得更高

近年来,越来越多的政府和执法机构使用无人机从空中鸟瞰。为了高效执行任务,无人机必须能够快速机动到预定目标。快速机动使它们能够在复杂的环境中航行,并高效地完成任务。成为认证的无人机驾驶员的要求因国家/地区而异,但都要求您…

有一点好看的wordpress外贸独立站模板

手机配件wordpress外贸网站模板 充电器、移动电源、手机膜、手机电池、手机壳、手机转接头等手机配件wordpress外贸网站模板。 https://www.jianzhanpress.com/?p3809 车载电器wordpress外贸网站模板 车载吸尘器、空气净化器、行车记录仪、车载充电器、车载影音导航等车载电…

网络原理TCP_IP

文章目录 应用层自定义协议 传输层udp协议TCP协议1.确认应答2.超时重传3.连接管理建立连接, 三次握手断开连接, 四次挥手tcp的状态 4.滑动窗口5.流量控制6.拥塞控制7.延时应答8.携带应答9.面向字节流10.异常情况 网络层IP协议地址管理路由选择 数据链路层以太网 应用层 自定义…

以创新筑牢安全盾牌,广师大隐盾科技照亮软件知识产权保护之路

“很感谢隐盾科技团队的各位成员对我司计算机软件代码保护的鼎力相助……”广州市硬科技百强企业在给予隐盾科技团队的感谢信中写道。据了解,该公司在使用了隐盾科技团队研发的隐盾代码虚拟化系统后,企业开发盗版率从45%降至0%、保护该企业年侵权成本超过…

redis5种数据类型应用场景

Redis提供了以下五种基本数据类型及其应用场景: 1 , String(字符串): 适用场景:用于存储统计网站访问数量、当前在线人数等信息。此外,它也适用于存#### 储JPG图片或者序列化的对象。 2 , Hash&#xff08…

预约自习室

预约自习室 1、技术介绍 自习室预约系统的后端开发语言采用Node,后端开发框架采用Express,数据库采用的Node的最佳搭档MySQL。采用Vue作为前端开发框架,Element-UI作为开发的组件库,微信小程序。期间采用axios实现网页数据获取&a…

精细调度:Apache DolphinScheduler脚本深度解析

在现代数据处理和工作流管理中,Apache DolphinScheduler以其灵活性和强大的调度能力受到开发者的广泛欢迎。 本文将逐步解析DolphinScheduler的关键脚本,希望能提供一个详尽的操作指南,帮助大家掌握安装、配置和操作的每一步。 建立在./bin/e…

精品中国货出海wordpress外贸独立站建站模板

旗袍唐装wordpress外贸网站模板 旗袍、唐装、华服wordpress外贸网站模板,适合做衣服生意的外贸公司官网使用。 https://www.jianzhanpress.com/?p3695 劳动防护wordpress外贸独立站模板 劳动防护wordpress外贸独立站模板,劳动保护、劳动防护用品外贸…

数字创新的风口:创业者如何在Web3时代抢占先机

随着区块链技术的不断发展,Web3正成为数字创新的新风口,为创业者们带来了前所未有的机遇和挑战。本文将从另一个角度探讨Web3对创业者的影响,并提出创业者在Web3时代抢占先机的策略和方法。 1. Web3重新定义了商业模式 Web3不仅仅是一种技术…

无人机生态环境监测、图像处理与GIS数据分析

构建“天空地”一体化监测体系是新形势下生态、环境、水文、农业、林业、气象等资源环境领域的重大需求,无人机生态环境监测在一体化监测体系中扮演着极其重要的角色。通过无人机航空遥感技术可以实现对地表空间要素的立体观测,获取丰富多样的地理空间数…

app逆向-ratel框架-AES,DES,MD5,SHA1加密算法java hook程序

一、前言 AES(高级加密标准)、DES(数据加密标准)、MD5(消息摘要算法5)和SHA-1(安全哈希算法1)都是常见的加密算法,用于数据加密和哈希计算。 二、加密算法实现 1、创建…

Linux第71步_将linux中的多个文件编译成一个驱动模块

学习目的:采用旧字符设备测试linux系统点灯,进一步熟悉其设计原理。采用多文件参与编译,深度学习编写Makefile,有利于实现驱动模块化设计。 1、创建MyOldLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home…

14、电源管理入门之Watchdog看门狗

目录 1. 软硬件watchdog的区别 2. 软件看门狗 2.1 kernel watchdog 2.1.1 soft lockup 2.1.1 hard lockup 2.2 用户态watchdog 2.2.1 softdog 2.2.1 hardware watchdog 3. 硬件看门狗 3.1 硬件寄存器介绍 3.2 喂狗操作 3.3 watchdog硬件驱动编写 参考: 看门狗,又…

量化人这样用Jupyter(2) - JupySQL, D-tale

当我们使用 Jupyter 时,很显然我们的主要目的是探索数据。这篇文章将介绍如何利用 JupySQL 来进行数据查询–甚至代替你正在使用的 Navicat, dbeaver 或者 pgAdmin。此外,我们还将介绍如何更敏捷地探索数据,相信这些工具,可以帮你省下 90%的 coding 时间。 原文发表在这里…

excel统计分析——正交设计

参考资料:生物统计学 单因素试验通常采用完全随机设计活动随机区组设计;两因素试验通常采用析因设计;多因素试验不考虑因素间的互作时,可以采用拉丁方设计或正交拉丁方设计;需要考虑因素间的互作时,析因设计…