作者 赵彬吉

update

<?php
namespace App\Console\Commands;
use App\Helper\Arr;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Process\Process;
class DiffDb extends Command
{
protected $signature = 'project:diff_db';
/**
* The console command description.
*
* @var string
*/
protected $description = '对比数据库结构';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
public function handle()
{
//C端
// $process = new Process(['git', 'pull']);
// $process->run();
// dump($process->getExitCodeText());
// dump($process->getExitCode());
// dump($process->getErrorOutput());
// $output = explode(PHP_EOL, $process->getOutput());
// dump($output);
// exit;
$custom_mysql_config = [
'database.connections.custom_mysql.host' => '43.154.15.250',
'database.connections.custom_mysql.port' => '6063',
'database.connections.custom_mysql.database' => 'globalso_v6',
'database.connections.custom_mysql.username' => 'globalso_v6',
'database.connections.custom_mysql.password' => 'PFxFdzj4ha6w7T3j',
];
config($custom_mysql_config);
$this->output->writeln("开始进行数据表对比!");
$tablesSource = DB::select("show tables");
$tablesRemote = DB::connection('custom_mysql')->select("show tables");
$tablesSource = array_map(function($item){
return Arr::first($item);
}, $tablesSource);
$tablesRemote = array_map(function($item){
return Arr::first($item);
}, $tablesRemote);
$tablesNotInRemote = [];
$tablesInRemote = [];
foreach ($tablesSource as $t) {
if (!in_array($t, $tablesRemote)) {
$tablesNotInRemote[] = $t;
} else {
$tablesInRemote[] = $t;
}
}
//print reports
echo "本地存在,但是不在custom_mysql中的表:" . PHP_EOL;
echo ">>>>>>==================================<<<<<<" . PHP_EOL;
foreach ($tablesNotInRemote as $t) {
echo $t . PHP_EOL;
}
echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
echo "本地与custom_mysql结构不一致的表:" . PHP_EOL;
echo ">>>>>>==================================<<<<<<" . PHP_EOL;
$only127 = $onlyRemote = $modify127 = [];
foreach ($tablesInRemote as $t) {
$columns127 = DB::select("show columns from `{$t}`");
foreach ($columns127 as &$item){
$item = get_object_vars($item);
}
$columnsRemote = DB::connection('custom_mysql')->select("show columns from `{$t}`");
foreach ($columnsRemote as &$item){
$item = get_object_vars($item);
}
$fields127 = $fieldsRemote = [];
foreach ($columns127 as $v) {
$fields127[$v['Field']] = $v;
}
foreach ($columnsRemote as $v) {
$fieldsRemote[$v['Field']] = $v;
}
foreach ($fields127 as $f => $column) {
if (!isset($fieldsRemote[$f])) {
$only127[$t][] = $f;
} else if ($column !== $fieldsRemote[$f]) {
dump($column);
dump($fieldsRemote[$f]);
$modify127[$t][] = $f;
}
}
foreach ($fieldsRemote as $f => $column) {
if (!isset($fields127[$f])) {
$onlyRemote[$t][] = $f;
}
}
}
if (!empty($only127)) {
echo "只本地存在:" . PHP_EOL;
foreach ($only127 as $t => $columns) {
echo $t . ":";
foreach ($columns as $field) {
echo $field . "\t";
}
echo PHP_EOL;
}
}
if (!empty($onlyRemote)) {
echo "只custom_mysql存在:" . PHP_EOL;
foreach ($onlyRemote as $t => $columns) {
echo $t . ":";
foreach ($columns as $field) {
echo $field . "\t";
}
echo PHP_EOL;
}
}
if (!empty($modify127)) {
echo "本地更新:" . PHP_EOL;
foreach ($modify127 as $t => $columns) {
echo $t . ":";
foreach ($columns as $field) {
echo $field . "\t";
}
echo PHP_EOL;
}
}
echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
}
}
... ...
... ... @@ -5,6 +5,8 @@ namespace App\Http\Controllers\Aside;
use App\Enums\Common\Code;
use App\Http\Controllers\Bside\BaseController;
use App\Http\Logic\Aside\ServerConfigLogic;
use App\Http\Requests\Aside\ServerConfigRequest;
use App\Models\Project as ProjectModel;
/**
... ... @@ -33,4 +35,16 @@ class ProjectController extends BaseController
public function add(){
$projectModel = new ProjectModel();
}
/**
* 保存配置
* @param ServerConfigRequest $request
* @param ServerConfigLogic $logic
* @author zbj
* @date 2023/4/23
*/
public function saveServerConfig(ServerConfigRequest $request, ServerConfigLogic $logic){
$data = $logic->save($this->param);
return $this->success($data);
}
}
... ...
<?php
namespace App\Http\Logic\Aside;
use App\Models\Product\Product;
use App\Models\ServerConfig;
use Illuminate\Support\Facades\DB;
/**
* Class ServerConfigLogic
* @package App\Http\Logic\Aside
* @author zbj
* @date 2023/4/23
*/
class ServerConfigLogic extends BaseLogic
{
public function __construct()
{
parent::__construct();
$this->model = new ServerConfig();
}
public function save($param)
{
DB::beginTransaction();
try {
$res = parent::save($param);
$data = ['sql_id' => $res['id']];
if ($param['type'] == ServerConfig::TYPE_SERVER) {
$data = ['serve_id' => $res['id']];
}
ProjectLogic::save($data);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
dump($e->getMessage());
$this->fail('保存失败');
}
}
}
... ...
... ... @@ -8,6 +8,7 @@ use App\Exceptions\AsideGlobalException;
use App\Exceptions\BsideGlobalException;
use App\Helper\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
/**
* @notes: 逻辑层基类 控制器调用 统一返回 统一抛出异常
... ... @@ -132,8 +133,11 @@ class Logic
$this->fail('数据不存在或者已经删除');
}
}
$columns = Schema::getColumnListing($this->model->getTable());
foreach ($param as $name => $value){
$this->model[$name] = $value;
if(in_array($name, $columns)){
$this->model[$name] = $value;
}
}
$res = $this->model->save();
... ...
<?php
namespace App\Http\Requests\Aside;
use App\Models\ServerConfig;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
/**
* Class ServerConfigRequest
* @package App\Http\Requests\Aside
* @author zbj
* @date 2023/4/23
*/
class ServerConfigRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'type' => ['required', Rule::in(array_keys(ServerConfig::typeMap()))],
'title'=>'required|max:50',
'host'=>'required|ip',
'user'=>'required',
'password'=>'required',
'port'=>'required',
];
}
public function messages()
{
return [
'type.required' => '请选择配置类型',
'title.required' => '请输入配置名称',
'title.max' => '配置名称不能超过50个字符',
'host.max' => '请输入IP',
'host.ip' => 'IP格式不正确',
'user.required' => '请输入用户名',
'password.required' => '请输入密码',
'port.required' => '请输入端口',
];
}
}
... ...
... ... @@ -38,7 +38,7 @@ class Project extends Base
*/
public function serverConfig()
{
return self::hasOne(ServeConfig::class, 'id', 'serve_id');
return self::hasOne(ServerConfig::class, 'id', 'serve_id');
}
/**
... ... @@ -47,7 +47,7 @@ class Project extends Base
*/
public function mysqlConfig()
{
return self::hasOne(ServeConfig::class, 'id', 'mysql_id');
return self::hasOne(ServerConfig::class, 'id', 'mysql_id');
}
/**
... ... @@ -56,7 +56,7 @@ class Project extends Base
*/
public function redisConfig()
{
return self::hasOne(ServeConfig::class, 'id', 'redis_id');
return self::hasOne(ServerConfig::class, 'id', 'redis_id');
}
/**
... ...
... ... @@ -13,7 +13,7 @@ namespace App\Models;
* Class ServeConfig
* @package App\Models
*/
class ServeConfig extends Base
class ServerConfig extends Base
{
/**
* @var string
... ... @@ -33,6 +33,19 @@ class ServeConfig extends Base
const TYPE_REDIS = 3;
/**
* @return string[]
* @author zbj
* @date 2023/4/23
*/
public static function typeMap(){
return [
self::TYPE_SERVER => '服务器',
self::TYPE_MYSQL => 'MySQL',
// self::TYPE_REDIS => 'Redis',
];
}
/**
* 用户名加密
* @param $value
*/
... ... @@ -83,4 +96,4 @@ class ServeConfig extends Base
return decrypt($this->port);
}
}
\ No newline at end of file
}
... ...
... ... @@ -9,6 +9,8 @@
namespace App\Services;
use App\Models\Project;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
/**
* Class ProjectServer
... ... @@ -18,7 +20,7 @@ class ProjectServer extends BaseService
{
/**
* @param $project_id
* @return bool
* @return Project|false
*/
public static function useProject($project_id)
{
... ... @@ -32,6 +34,47 @@ class ProjectServer extends BaseService
config(['database.connections.custom_mysql.username' => $project->mysqlConfig()->user]);
config(['database.connections.custom_mysql.password' => $project->mysqlConfig()->password]);
// 设置 redis 配置
return $project;
}
/**
* 创建数据库
* @param $project_id
* @author zbj
* @date 2023/4/23
*/
public static function createDatabase($project_id){
$project = self::useProject($project_id);
DB::connection('custom_mysql')->statement("CREATE DATABASE IF NOT EXISTS {$project->databaseName()}");
}
/**
* @param $project_id
* @return bool
* @throws \Doctrine\DBAL\Exception
* @author zbj
* @date 2023/4/23
*/
public static function initTable($project_id){
$project = self::useProject($project_id);
$database_name = DB::connection('custom_tmp_mysql')->getDatabaseName();
$table = Schema::connection('custom_tmp_mysql')->getAllTables();
$table = array_column($table, 'Tables_in_' . $database_name);
foreach ($table as $v) {
$has_table = Schema::connection('custom_mysql')->hasTable($v);
if ($has_table)
continue;
$connection = DB::connection('custom_tmp_mysql');
$sql = $connection->getDoctrineSchemaManager()
->getDatabasePlatform()
->getCreateTableSQL($connection->getDoctrineSchemaManager()->listTableDetails($v));
DB::connection('custom_mysql')->select($sql[0]);
}
return true;
}
}
... ...
... ... @@ -42,6 +42,10 @@ Route::middleware(['web'])->group(function (){ //admin用渲染默认要加上w
});
});
//项目管理
Route::prefix('project')->group(function () {
Route::post('/save_server_config', [Aside\ProjectController::class, 'saveServerConfig'])->name('admin.project.save_server_config');
});
});
... ...