作者 赵彬吉

update

  1 +<?php
  2 +
  3 +namespace App\Console\Commands;
  4 +
  5 +
  6 +
  7 +
  8 +use App\Helper\Arr;
  9 +use Illuminate\Console\Command;
  10 +use Illuminate\Support\Facades\Artisan;
  11 +use Illuminate\Support\Facades\DB;
  12 +use Symfony\Component\Process\Process;
  13 +
  14 +class DiffDb extends Command
  15 +{
  16 + protected $signature = 'project:diff_db';
  17 +
  18 + /**
  19 + * The console command description.
  20 + *
  21 + * @var string
  22 + */
  23 + protected $description = '对比数据库结构';
  24 +
  25 + /**
  26 + * Create a new command instance.
  27 + *
  28 + * @return void
  29 + */
  30 + public function __construct()
  31 + {
  32 + parent::__construct();
  33 + }
  34 +
  35 + public function handle()
  36 + {
  37 + //C端
  38 +// $process = new Process(['git', 'pull']);
  39 +// $process->run();
  40 +// dump($process->getExitCodeText());
  41 +// dump($process->getExitCode());
  42 +// dump($process->getErrorOutput());
  43 +// $output = explode(PHP_EOL, $process->getOutput());
  44 +// dump($output);
  45 +// exit;
  46 + $custom_mysql_config = [
  47 + 'database.connections.custom_mysql.host' => '43.154.15.250',
  48 + 'database.connections.custom_mysql.port' => '6063',
  49 + 'database.connections.custom_mysql.database' => 'globalso_v6',
  50 + 'database.connections.custom_mysql.username' => 'globalso_v6',
  51 + 'database.connections.custom_mysql.password' => 'PFxFdzj4ha6w7T3j',
  52 + ];
  53 + config($custom_mysql_config);
  54 +
  55 + $this->output->writeln("开始进行数据表对比!");
  56 + $tablesSource = DB::select("show tables");
  57 + $tablesRemote = DB::connection('custom_mysql')->select("show tables");
  58 + $tablesSource = array_map(function($item){
  59 + return Arr::first($item);
  60 + }, $tablesSource);
  61 + $tablesRemote = array_map(function($item){
  62 + return Arr::first($item);
  63 + }, $tablesRemote);
  64 +
  65 +
  66 + $tablesNotInRemote = [];
  67 + $tablesInRemote = [];
  68 +
  69 + foreach ($tablesSource as $t) {
  70 + if (!in_array($t, $tablesRemote)) {
  71 + $tablesNotInRemote[] = $t;
  72 + } else {
  73 + $tablesInRemote[] = $t;
  74 + }
  75 + }
  76 +
  77 + //print reports
  78 + echo "本地存在,但是不在custom_mysql中的表:" . PHP_EOL;
  79 + echo ">>>>>>==================================<<<<<<" . PHP_EOL;
  80 + foreach ($tablesNotInRemote as $t) {
  81 + echo $t . PHP_EOL;
  82 + }
  83 + echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
  84 +
  85 +
  86 + echo "本地与custom_mysql结构不一致的表:" . PHP_EOL;
  87 + echo ">>>>>>==================================<<<<<<" . PHP_EOL;
  88 +
  89 + $only127 = $onlyRemote = $modify127 = [];
  90 + foreach ($tablesInRemote as $t) {
  91 + $columns127 = DB::select("show columns from `{$t}`");
  92 + foreach ($columns127 as &$item){
  93 + $item = get_object_vars($item);
  94 + }
  95 + $columnsRemote = DB::connection('custom_mysql')->select("show columns from `{$t}`");
  96 + foreach ($columnsRemote as &$item){
  97 + $item = get_object_vars($item);
  98 + }
  99 +
  100 + $fields127 = $fieldsRemote = [];
  101 + foreach ($columns127 as $v) {
  102 + $fields127[$v['Field']] = $v;
  103 + }
  104 + foreach ($columnsRemote as $v) {
  105 + $fieldsRemote[$v['Field']] = $v;
  106 + }
  107 +
  108 + foreach ($fields127 as $f => $column) {
  109 + if (!isset($fieldsRemote[$f])) {
  110 + $only127[$t][] = $f;
  111 + } else if ($column !== $fieldsRemote[$f]) {
  112 + dump($column);
  113 + dump($fieldsRemote[$f]);
  114 + $modify127[$t][] = $f;
  115 + }
  116 + }
  117 +
  118 + foreach ($fieldsRemote as $f => $column) {
  119 + if (!isset($fields127[$f])) {
  120 + $onlyRemote[$t][] = $f;
  121 + }
  122 + }
  123 + }
  124 +
  125 + if (!empty($only127)) {
  126 + echo "只本地存在:" . PHP_EOL;
  127 + foreach ($only127 as $t => $columns) {
  128 + echo $t . ":";
  129 + foreach ($columns as $field) {
  130 + echo $field . "\t";
  131 + }
  132 + echo PHP_EOL;
  133 + }
  134 + }
  135 + if (!empty($onlyRemote)) {
  136 + echo "只custom_mysql存在:" . PHP_EOL;
  137 + foreach ($onlyRemote as $t => $columns) {
  138 + echo $t . ":";
  139 + foreach ($columns as $field) {
  140 + echo $field . "\t";
  141 + }
  142 + echo PHP_EOL;
  143 + }
  144 + }
  145 + if (!empty($modify127)) {
  146 + echo "本地更新:" . PHP_EOL;
  147 + foreach ($modify127 as $t => $columns) {
  148 + echo $t . ":";
  149 + foreach ($columns as $field) {
  150 + echo $field . "\t";
  151 + }
  152 + echo PHP_EOL;
  153 + }
  154 + }
  155 + echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
  156 + }
  157 +}
@@ -5,6 +5,8 @@ namespace App\Http\Controllers\Aside; @@ -5,6 +5,8 @@ namespace App\Http\Controllers\Aside;
5 use App\Enums\Common\Code; 5 use App\Enums\Common\Code;
6 use App\Http\Controllers\Bside\BaseController; 6 use App\Http\Controllers\Bside\BaseController;
7 7
  8 +use App\Http\Logic\Aside\ServerConfigLogic;
  9 +use App\Http\Requests\Aside\ServerConfigRequest;
8 use App\Models\Project as ProjectModel; 10 use App\Models\Project as ProjectModel;
9 11
10 /** 12 /**
@@ -33,4 +35,16 @@ class ProjectController extends BaseController @@ -33,4 +35,16 @@ class ProjectController extends BaseController
33 public function add(){ 35 public function add(){
34 $projectModel = new ProjectModel(); 36 $projectModel = new ProjectModel();
35 } 37 }
  38 +
  39 + /**
  40 + * 保存配置
  41 + * @param ServerConfigRequest $request
  42 + * @param ServerConfigLogic $logic
  43 + * @author zbj
  44 + * @date 2023/4/23
  45 + */
  46 + public function saveServerConfig(ServerConfigRequest $request, ServerConfigLogic $logic){
  47 + $data = $logic->save($this->param);
  48 + return $this->success($data);
  49 + }
36 } 50 }
  1 +<?php
  2 +
  3 +namespace App\Http\Logic\Aside;
  4 +
  5 +use App\Models\Product\Product;
  6 +use App\Models\ServerConfig;
  7 +use Illuminate\Support\Facades\DB;
  8 +
  9 +/**
  10 + * Class ServerConfigLogic
  11 + * @package App\Http\Logic\Aside
  12 + * @author zbj
  13 + * @date 2023/4/23
  14 + */
  15 +class ServerConfigLogic extends BaseLogic
  16 +{
  17 + public function __construct()
  18 + {
  19 + parent::__construct();
  20 +
  21 + $this->model = new ServerConfig();
  22 + }
  23 +
  24 +
  25 + public function save($param)
  26 + {
  27 + DB::beginTransaction();
  28 + try {
  29 + $res = parent::save($param);
  30 +
  31 + $data = ['sql_id' => $res['id']];
  32 + if ($param['type'] == ServerConfig::TYPE_SERVER) {
  33 + $data = ['serve_id' => $res['id']];
  34 + }
  35 + ProjectLogic::save($data);
  36 +
  37 + DB::commit();
  38 + } catch (\Exception $e) {
  39 + DB::rollBack();
  40 +
  41 + dump($e->getMessage());
  42 + $this->fail('保存失败');
  43 + }
  44 + }
  45 +}
@@ -8,6 +8,7 @@ use App\Exceptions\AsideGlobalException; @@ -8,6 +8,7 @@ use App\Exceptions\AsideGlobalException;
8 use App\Exceptions\BsideGlobalException; 8 use App\Exceptions\BsideGlobalException;
9 use App\Helper\Arr; 9 use App\Helper\Arr;
10 use Illuminate\Support\Facades\Cache; 10 use Illuminate\Support\Facades\Cache;
  11 +use Illuminate\Support\Facades\Schema;
11 12
12 /** 13 /**
13 * @notes: 逻辑层基类 控制器调用 统一返回 统一抛出异常 14 * @notes: 逻辑层基类 控制器调用 统一返回 统一抛出异常
@@ -132,8 +133,11 @@ class Logic @@ -132,8 +133,11 @@ class Logic
132 $this->fail('数据不存在或者已经删除'); 133 $this->fail('数据不存在或者已经删除');
133 } 134 }
134 } 135 }
  136 + $columns = Schema::getColumnListing($this->model->getTable());
135 foreach ($param as $name => $value){ 137 foreach ($param as $name => $value){
136 - $this->model[$name] = $value; 138 + if(in_array($name, $columns)){
  139 + $this->model[$name] = $value;
  140 + }
137 } 141 }
138 142
139 $res = $this->model->save(); 143 $res = $this->model->save();
  1 +<?php
  2 +
  3 +namespace App\Http\Requests\Aside;
  4 +
  5 +use App\Models\ServerConfig;
  6 +use Illuminate\Foundation\Http\FormRequest;
  7 +use Illuminate\Validation\Rule;
  8 +
  9 +/**
  10 + * Class ServerConfigRequest
  11 + * @package App\Http\Requests\Aside
  12 + * @author zbj
  13 + * @date 2023/4/23
  14 + */
  15 +class ServerConfigRequest extends FormRequest
  16 +{
  17 + /**
  18 + * Determine if the user is authorized to make this request.
  19 + *
  20 + * @return bool
  21 + */
  22 + public function authorize()
  23 + {
  24 + return true;
  25 + }
  26 +
  27 + /**
  28 + * Get the validation rules that apply to the request.
  29 + *
  30 + * @return array
  31 + */
  32 + public function rules()
  33 + {
  34 + return [
  35 + 'type' => ['required', Rule::in(array_keys(ServerConfig::typeMap()))],
  36 + 'title'=>'required|max:50',
  37 + 'host'=>'required|ip',
  38 + 'user'=>'required',
  39 + 'password'=>'required',
  40 + 'port'=>'required',
  41 + ];
  42 + }
  43 +
  44 + public function messages()
  45 + {
  46 + return [
  47 + 'type.required' => '请选择配置类型',
  48 + 'title.required' => '请输入配置名称',
  49 + 'title.max' => '配置名称不能超过50个字符',
  50 + 'host.max' => '请输入IP',
  51 + 'host.ip' => 'IP格式不正确',
  52 + 'user.required' => '请输入用户名',
  53 + 'password.required' => '请输入密码',
  54 + 'port.required' => '请输入端口',
  55 + ];
  56 + }
  57 +
  58 +}
@@ -38,7 +38,7 @@ class Project extends Base @@ -38,7 +38,7 @@ class Project extends Base
38 */ 38 */
39 public function serverConfig() 39 public function serverConfig()
40 { 40 {
41 - return self::hasOne(ServeConfig::class, 'id', 'serve_id'); 41 + return self::hasOne(ServerConfig::class, 'id', 'serve_id');
42 } 42 }
43 43
44 /** 44 /**
@@ -47,7 +47,7 @@ class Project extends Base @@ -47,7 +47,7 @@ class Project extends Base
47 */ 47 */
48 public function mysqlConfig() 48 public function mysqlConfig()
49 { 49 {
50 - return self::hasOne(ServeConfig::class, 'id', 'mysql_id'); 50 + return self::hasOne(ServerConfig::class, 'id', 'mysql_id');
51 } 51 }
52 52
53 /** 53 /**
@@ -56,7 +56,7 @@ class Project extends Base @@ -56,7 +56,7 @@ class Project extends Base
56 */ 56 */
57 public function redisConfig() 57 public function redisConfig()
58 { 58 {
59 - return self::hasOne(ServeConfig::class, 'id', 'redis_id'); 59 + return self::hasOne(ServerConfig::class, 'id', 'redis_id');
60 } 60 }
61 61
62 /** 62 /**
@@ -13,7 +13,7 @@ namespace App\Models; @@ -13,7 +13,7 @@ namespace App\Models;
13 * Class ServeConfig 13 * Class ServeConfig
14 * @package App\Models 14 * @package App\Models
15 */ 15 */
16 -class ServeConfig extends Base 16 +class ServerConfig extends Base
17 { 17 {
18 /** 18 /**
19 * @var string 19 * @var string
@@ -33,6 +33,19 @@ class ServeConfig extends Base @@ -33,6 +33,19 @@ class ServeConfig extends Base
33 const TYPE_REDIS = 3; 33 const TYPE_REDIS = 3;
34 34
35 /** 35 /**
  36 + * @return string[]
  37 + * @author zbj
  38 + * @date 2023/4/23
  39 + */
  40 + public static function typeMap(){
  41 + return [
  42 + self::TYPE_SERVER => '服务器',
  43 + self::TYPE_MYSQL => 'MySQL',
  44 +// self::TYPE_REDIS => 'Redis',
  45 + ];
  46 + }
  47 +
  48 + /**
36 * 用户名加密 49 * 用户名加密
37 * @param $value 50 * @param $value
38 */ 51 */
@@ -83,4 +96,4 @@ class ServeConfig extends Base @@ -83,4 +96,4 @@ class ServeConfig extends Base
83 return decrypt($this->port); 96 return decrypt($this->port);
84 } 97 }
85 98
86 -}  
  99 +}
@@ -9,6 +9,8 @@ @@ -9,6 +9,8 @@
9 namespace App\Services; 9 namespace App\Services;
10 10
11 use App\Models\Project; 11 use App\Models\Project;
  12 +use Illuminate\Support\Facades\DB;
  13 +use Illuminate\Support\Facades\Schema;
12 14
13 /** 15 /**
14 * Class ProjectServer 16 * Class ProjectServer
@@ -18,7 +20,7 @@ class ProjectServer extends BaseService @@ -18,7 +20,7 @@ class ProjectServer extends BaseService
18 { 20 {
19 /** 21 /**
20 * @param $project_id 22 * @param $project_id
21 - * @return bool 23 + * @return Project|false
22 */ 24 */
23 public static function useProject($project_id) 25 public static function useProject($project_id)
24 { 26 {
@@ -32,6 +34,47 @@ class ProjectServer extends BaseService @@ -32,6 +34,47 @@ class ProjectServer extends BaseService
32 config(['database.connections.custom_mysql.username' => $project->mysqlConfig()->user]); 34 config(['database.connections.custom_mysql.username' => $project->mysqlConfig()->user]);
33 config(['database.connections.custom_mysql.password' => $project->mysqlConfig()->password]); 35 config(['database.connections.custom_mysql.password' => $project->mysqlConfig()->password]);
34 // 设置 redis 配置 36 // 设置 redis 配置
  37 + return $project;
  38 + }
  39 +
  40 +
  41 + /**
  42 + * 创建数据库
  43 + * @param $project_id
  44 + * @author zbj
  45 + * @date 2023/4/23
  46 + */
  47 + public static function createDatabase($project_id){
  48 + $project = self::useProject($project_id);
  49 + DB::connection('custom_mysql')->statement("CREATE DATABASE IF NOT EXISTS {$project->databaseName()}");
  50 + }
  51 +
  52 +
  53 + /**
  54 + * @param $project_id
  55 + * @return bool
  56 + * @throws \Doctrine\DBAL\Exception
  57 + * @author zbj
  58 + * @date 2023/4/23
  59 + */
  60 + public static function initTable($project_id){
  61 + $project = self::useProject($project_id);
  62 + $database_name = DB::connection('custom_tmp_mysql')->getDatabaseName();
  63 +
  64 + $table = Schema::connection('custom_tmp_mysql')->getAllTables();
  65 + $table = array_column($table, 'Tables_in_' . $database_name);
  66 + foreach ($table as $v) {
  67 + $has_table = Schema::connection('custom_mysql')->hasTable($v);
  68 + if ($has_table)
  69 + continue;
  70 +
  71 + $connection = DB::connection('custom_tmp_mysql');
  72 + $sql = $connection->getDoctrineSchemaManager()
  73 + ->getDatabasePlatform()
  74 + ->getCreateTableSQL($connection->getDoctrineSchemaManager()->listTableDetails($v));
  75 +
  76 + DB::connection('custom_mysql')->select($sql[0]);
  77 + }
35 return true; 78 return true;
36 } 79 }
37 } 80 }
@@ -42,6 +42,10 @@ Route::middleware(['web'])->group(function (){ //admin用渲染默认要加上w @@ -42,6 +42,10 @@ Route::middleware(['web'])->group(function (){ //admin用渲染默认要加上w
42 }); 42 });
43 }); 43 });
44 44
  45 + //项目管理
  46 + Route::prefix('project')->group(function () {
  47 + Route::post('/save_server_config', [Aside\ProjectController::class, 'saveServerConfig'])->name('admin.project.save_server_config');
  48 + });
45 49
46 }); 50 });
47 51