mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-01 15:32:48 +08:00
新增生成数据库迁移代码命令
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -13,4 +13,5 @@ app/test/
|
||||
vendor
|
||||
runtime
|
||||
ul.db
|
||||
/app/tools/controller/Install.php
|
||||
/app/tools/controller/Install.php
|
||||
/app/common/command/curd/migrate_output.php
|
||||
202
app/common/command/curd/Migrate.php
Normal file
202
app/common/command/curd/Migrate.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\command\curd;
|
||||
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\facade\App;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Migrate extends Command
|
||||
{
|
||||
|
||||
protected $table;
|
||||
protected $tablePrefix;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
// 指令配置
|
||||
$this->setName('curd:migrate')
|
||||
->addOption('table', 't', Option::VALUE_REQUIRED, '主表名')
|
||||
->addOption('tableName', '', Option::VALUE_OPTIONAL, '要生成的表名')
|
||||
->addOption('fileName', '', Option::VALUE_OPTIONAL, '要生成的文件名')
|
||||
->addOption('force', 'f', Option::VALUE_NONE, '强制生成')
|
||||
->setDescription('the curd:migrate command');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 指令输出
|
||||
$output->writeln('curd:migrate');
|
||||
|
||||
$table = $input->getOption('table');
|
||||
$file_name = $input->getOption('fileName');
|
||||
$table_name = $input->getOption('tableName');
|
||||
$force = $input->getOption('force');
|
||||
|
||||
if (empty($table)) {
|
||||
$output->error('请输入表名');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($table_name)) {
|
||||
$table_name = $table;
|
||||
}
|
||||
|
||||
if (empty($file_name)) {
|
||||
$file_name = $table_name;
|
||||
}
|
||||
$this->table = $table;
|
||||
|
||||
|
||||
$this->database = config('database.connections.mysql.database');
|
||||
$this->tablePrefix = config('database.connections.mysql.prefix');
|
||||
|
||||
$table_info_sql = "select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='{$this->database}' and TABLE_NAME='{$this->tablePrefix}{$this->table}'";
|
||||
|
||||
$table_info = Db::query($table_info_sql);
|
||||
|
||||
if (empty($table_info)) {
|
||||
$output->error('表不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
$dist_file_path = App::getRootPath() . '/database/migrations/' . date('YmdHis') . '_' . $file_name . '.php';
|
||||
|
||||
$patt_path = App::getRootPath() . '/database/migrations/*' . $file_name . '.php';
|
||||
|
||||
$patt_files = glob($patt_path);
|
||||
|
||||
|
||||
$is_extis = false;
|
||||
foreach ($patt_files as $patt_file) {
|
||||
|
||||
|
||||
$patt = '/.*database\/migrations\/\d+_' . $file_name . '.php$/';
|
||||
|
||||
$preg_result = preg_match($patt, $patt_file);
|
||||
|
||||
|
||||
if ($preg_result) {
|
||||
$is_extis = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_extis) {
|
||||
$output->error('文件已存在:' . $patt_files[0]);
|
||||
if (!$force) {
|
||||
$confirm_force = $output->confirm($input, '确定要覆盖文件吗?', false);
|
||||
|
||||
if (!$confirm_force) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$output->highlight('执行覆盖操作');
|
||||
|
||||
$dist_file_path = $patt_files[0];
|
||||
}
|
||||
|
||||
|
||||
$columns = Db::query("SHOW FULL COLUMNS FROM {$this->tablePrefix}{$this->table}");
|
||||
|
||||
$data['class_name'] = \think\helper\Str::studly($file_name);
|
||||
|
||||
|
||||
$table_columns = [];
|
||||
|
||||
$table_keys = [];
|
||||
$table_keys_text = [];
|
||||
$table_keys_uni = [];
|
||||
|
||||
foreach ($columns as $column) {
|
||||
|
||||
if ($column['Field'] == 'id') {
|
||||
continue;
|
||||
}
|
||||
$column_item = [];
|
||||
$column_item['options'] = [];
|
||||
|
||||
$column_item['field'] = $column['Field'];
|
||||
|
||||
$column_item['type'] = '';
|
||||
|
||||
$type = $column['Type'];
|
||||
|
||||
if (strpos($type, '(') !== false) {
|
||||
// 带有长度
|
||||
|
||||
$type_info = explode('(', $type);
|
||||
$column_item['type'] = $type_info[0];
|
||||
|
||||
$length = substr($type_info[1], 0, strpos($type_info[1], ')'));
|
||||
$column_item['options']['limit'] = $length;
|
||||
|
||||
if (strpos($type, 'unsigned') !== false) {
|
||||
// 无符号
|
||||
$column_item['options']['signed'] = 0;
|
||||
}
|
||||
} else {
|
||||
$column_item['type'] = $type;
|
||||
}
|
||||
|
||||
$column_item['options']['null'] = $column['Null'] == 'YES' ? 1 : 0;
|
||||
if ($column['Default'] !== null) {
|
||||
$column_item['options']['default'] = $column['Default'];
|
||||
}
|
||||
$column_item['options']['comment'] = $column['Comment'];
|
||||
|
||||
$key = $column['Key'];
|
||||
|
||||
if (!empty($key)) {
|
||||
if ($key == 'MUL') {
|
||||
if ($type == 'text' || $type == 'longtext') {
|
||||
|
||||
$table_keys_text[] = $column['Field'];
|
||||
} else {
|
||||
$table_keys[] = $column['Field'];
|
||||
}
|
||||
} else if ($key == 'UNI') {
|
||||
$table_keys_uni[] = $column['Field'];
|
||||
}
|
||||
}
|
||||
|
||||
$table_columns[] = $column_item;
|
||||
}
|
||||
|
||||
$type_map = [
|
||||
'bigint' => 'biginteger',
|
||||
'int' => 'integer',
|
||||
'varchar' => 'string',
|
||||
'smallint' => 'integer',
|
||||
'tinyint' => 'integer',
|
||||
'longtext' => 'text',
|
||||
];
|
||||
|
||||
foreach ($table_columns as &$column_item_set) {
|
||||
|
||||
if (isset($type_map[$column_item_set['type']])) {
|
||||
$column_item_set['type'] = $type_map[$column_item_set['type']];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$data['table_info'] = $table_info[0];
|
||||
$data['table'] = $table_name;
|
||||
$data['table_columns'] = $table_columns;
|
||||
$data['table_keys'] = $table_keys;
|
||||
$data['table_keys_uni'] = $table_keys_uni;
|
||||
$data['table_keys_text'] = $table_keys_text;
|
||||
|
||||
|
||||
$migrate_content = View::fetch(__DIR__ . '/migrate.tpl', $data);
|
||||
|
||||
file_put_contents(__DIR__ . '/migrate_output.php', "<?php\n\n" . $migrate_content);
|
||||
file_put_contents($dist_file_path, "<?php\n\n" . $migrate_content);
|
||||
}
|
||||
}
|
||||
40
app/common/command/curd/migrate.tpl
Normal file
40
app/common/command/curd/migrate.tpl
Normal file
@@ -0,0 +1,40 @@
|
||||
use think\migration\Migrator;
|
||||
use think\migration\db\Column;
|
||||
|
||||
class {$class_name} extends Migrator
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
|
||||
*
|
||||
* The following commands can be used in this method and Phinx will
|
||||
* automatically reverse them when rolling back:
|
||||
*
|
||||
* createTable
|
||||
* renameTable
|
||||
* addColumn
|
||||
* renameColumn
|
||||
* addIndex
|
||||
* addForeignKey
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('{$table}')
|
||||
->setComment('{$table_info.TABLE_COMMENT}')
|
||||
{volist name="table_columns" id="column"}->addColumn('{$column.field}', '{$column.type}', [{volist name="column.options" id="option"}'{$key}' => '{$option}', {/volist}])
|
||||
{/volist}
|
||||
{volist name="table_keys_uni" id="vo"}->addIndex('{$vo}',['unique'=>true])
|
||||
{/volist}
|
||||
{volist name="table_keys_text" id="vo"}->addIndex('{$vo}',['type'=>'fulltext'])
|
||||
{/volist}
|
||||
{volist name="table_keys" id="vo"}->addIndex('{$vo}')
|
||||
{/volist}->create();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
use app\common\command\admin\Version;
|
||||
use app\common\command\admin\ResetPassword;
|
||||
use app\common\command\curd\Migrate;
|
||||
use app\common\command\Timer;
|
||||
|
||||
return [
|
||||
@@ -15,6 +16,7 @@ return [
|
||||
'OssStatic' => 'app\common\command\OssStatic',
|
||||
ResetPassword::class,
|
||||
Timer::class,
|
||||
Version::class
|
||||
Version::class,
|
||||
Migrate::class
|
||||
],
|
||||
];
|
||||
|
||||
66
database/migrations/20220905222557_test_goods.php
Normal file
66
database/migrations/20220905222557_test_goods.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
use think\migration\Migrator;
|
||||
use think\migration\db\Column;
|
||||
|
||||
class TestGoods extends Migrator
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
|
||||
*
|
||||
* The following commands can be used in this method and Phinx will
|
||||
* automatically reverse them when rolling back:
|
||||
*
|
||||
* createTable
|
||||
* renameTable
|
||||
* addColumn
|
||||
* renameColumn
|
||||
* addIndex
|
||||
* addForeignKey
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('test_goods')
|
||||
->setComment('商品列表')
|
||||
->addColumn('cate_id', 'biginteger', ['limit' => '20', 'signed' => '0', 'null' => '0', 'default' => '0', 'comment' => '分类ID {relation} (table:mall_cate,relationBindSelect:title)',])
|
||||
->addColumn('title', 'char', ['limit' => '20', 'null' => '0', 'default' => '', 'comment' => '商品名称',])
|
||||
->addColumn('logo', 'char', ['limit' => '255', 'null' => '0', 'comment' => '商品logo {image}',])
|
||||
->addColumn('images', 'text', ['null' => '0', 'comment' => '商品图片 {images}',])
|
||||
->addColumn('describe', 'text', ['null' => '0', 'comment' => '商品描述 {editor}',])
|
||||
->addColumn('total_stock', 'integer', ['limit' => '11', 'signed' => '0', 'null' => '0', 'default' => '0', 'comment' => '总库存',])
|
||||
->addColumn('sort', 'integer', ['limit' => '11', 'signed' => '0', 'null' => '0', 'default' => '0', 'comment' => '排序',])
|
||||
->addColumn('status', 'integer', ['limit' => '1', 'signed' => '0', 'null' => '0', 'default' => '0', 'comment' => '状态 {radio} (0:正常,1:禁用)',])
|
||||
->addColumn('cert_file', 'string', ['limit' => '100', 'null' => '0', 'comment' => '合格证 {file}',])
|
||||
->addColumn('verfiy_file', 'text', ['null' => '0', 'comment' => '检测报告 {files}',])
|
||||
->addColumn('remark', 'char', ['limit' => '255', 'null' => '0', 'default' => '', 'comment' => '备注说明',])
|
||||
->addColumn('create_time', 'integer', ['limit' => '11', 'signed' => '0', 'null' => '0', 'default' => '0', 'comment' => '',])
|
||||
->addColumn('update_time', 'integer', ['limit' => '11', 'signed' => '0', 'null' => '0', 'default' => '0', 'comment' => '',])
|
||||
->addColumn('delete_time', 'integer', ['limit' => '11', 'signed' => '0', 'null' => '0', 'default' => '0', 'comment' => '',])
|
||||
->addColumn('publish_time', 'integer', ['limit' => '10', 'signed' => '0', 'null' => '0', 'comment' => '发布日期 {date} (date)',])
|
||||
->addColumn('sale_time', 'biginteger', ['limit' => '20', 'signed' => '0', 'null' => '0', 'comment' => '售卖日期 {date} (datetime)',])
|
||||
->addColumn('intro', 'string', ['limit' => '100', 'null' => '0', 'comment' => '简介 {textarea}',])
|
||||
->addColumn('time_status', 'integer', ['limit' => '5', 'signed' => '0', 'null' => '0', 'comment' => '秒杀状态 {select} (0:未参加,1:已开始,3:已结束)',])
|
||||
->addColumn('is_recommend', 'integer', ['limit' => '4', 'null' => '0', 'comment' => '是否推荐 {switch} (0:不推荐,1:推荐)',])
|
||||
->addColumn('shop_type', 'string', ['limit' => '100', 'null' => '0', 'comment' => '商品类型 {checkbox} (taobao:淘宝,jd:京东)',])
|
||||
->addColumn('tag', 'string', ['limit' => '100', 'null' => '0', 'comment' => '商品标签 {table} (table:mall_tag,type:checkbox,valueField:id,fieldName:title)',])
|
||||
->addColumn('tag_backup', 'string', ['limit' => '100', 'null' => '1', 'comment' => '商品标签(单选) {table} (table:mall_tag,type:radio,valueField:id,fieldName:title)',])
|
||||
->addColumn('from_area', 'string', ['limit' => '100', 'null' => '0', 'comment' => '产地 {city} (name-province:0,code:0)',])
|
||||
->addColumn('store_city', 'string', ['limit' => '100', 'null' => '0', 'default' => '山东省/临沂市', 'comment' => '仓库 {city} (level:city)',])
|
||||
->addColumn('tag_input', 'string', ['limit' => '100', 'null' => '0', 'comment' => '商品标签 (输入) {tag}',])
|
||||
->addColumn('uid', 'string', ['limit' => '100', 'null' => '0', 'comment' => '唯一id',])
|
||||
->addColumn('price', 'decimal', ['limit' => '10,2', 'null' => '1', 'comment' => '价格',])
|
||||
->addColumn('detail', 'text', ['null' => '1', 'comment' => '详情',])
|
||||
->addIndex('uid', ['unique' => true])
|
||||
->addIndex('detail', ['type' => 'fulltext'])
|
||||
->addIndex('cate_id')
|
||||
->create();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user