|
|
@@ -0,0 +1,92 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Console\Commands;
|
|
|
+
|
|
|
+use Illuminate\Console\Command;
|
|
|
+use Symfony\Component\Process\Process;
|
|
|
+
|
|
|
+class DbImport extends Command
|
|
|
+{
|
|
|
+ protected $signature = 'db:import
|
|
|
+ {file : Путь к .sql или .sql.gz файлу}
|
|
|
+ {--connection=mysql : Имя соединения из config/database.php}
|
|
|
+ {--force : Не запрашивать подтверждение}
|
|
|
+ {--drop : Очистить БД (DROP+CREATE) перед импортом}';
|
|
|
+
|
|
|
+ protected $description = 'Импорт SQL-дампа в базу данных через mysql';
|
|
|
+
|
|
|
+ public function handle(): int
|
|
|
+ {
|
|
|
+ $file = $this->argument('file');
|
|
|
+ if (!is_file($file)) {
|
|
|
+ $this->error("Файл не найден: {$file}");
|
|
|
+ return self::FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ $connection = $this->option('connection');
|
|
|
+ $config = config("database.connections.{$connection}");
|
|
|
+
|
|
|
+ if (!$config || !in_array($config['driver'] ?? null, ['mysql', 'mariadb'], true)) {
|
|
|
+ $this->error("Соединение {$connection} не найдено или не MySQL/MariaDB.");
|
|
|
+ return self::FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ $database = $config['database'];
|
|
|
+ $host = $config['host'] ?? '127.0.0.1';
|
|
|
+ $port = (string) ($config['port'] ?? '3306');
|
|
|
+ $user = $config['username'] ?? 'root';
|
|
|
+ $password = (string) ($config['password'] ?? '');
|
|
|
+
|
|
|
+ if (!$this->option('force') && !$this->confirm("Импортировать дамп в БД {$database}? Текущие данные будут перезаписаны.", false)) {
|
|
|
+ $this->warn('Отменено.');
|
|
|
+ return self::SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ $authHost = sprintf(
|
|
|
+ '--host=%s --port=%s --user=%s %s',
|
|
|
+ escapeshellarg($host),
|
|
|
+ escapeshellarg($port),
|
|
|
+ escapeshellarg($user),
|
|
|
+ $password !== '' ? '--password=' . escapeshellarg($password) : '',
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->option('drop')) {
|
|
|
+ $this->info("Пересоздаю БД {$database}...");
|
|
|
+ $sql = sprintf(
|
|
|
+ 'DROP DATABASE IF EXISTS `%s`; CREATE DATABASE `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;',
|
|
|
+ str_replace('`', '', $database),
|
|
|
+ str_replace('`', '', $database),
|
|
|
+ );
|
|
|
+ $dropCmd = "mysql {$authHost} -e " . escapeshellarg($sql);
|
|
|
+ $drop = Process::fromShellCommandline($dropCmd);
|
|
|
+ $drop->setTimeout(null);
|
|
|
+ $drop->run();
|
|
|
+ if (!$drop->isSuccessful()) {
|
|
|
+ $this->error('Ошибка пересоздания БД: ' . $drop->getErrorOutput());
|
|
|
+ return self::FAILURE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $isGz = str_ends_with($file, '.gz');
|
|
|
+ $reader = $isGz ? 'gunzip -c ' : 'cat ';
|
|
|
+ $cmd = $reader . escapeshellarg($file) . " | mysql {$authHost} --default-character-set=utf8mb4 " . escapeshellarg($database);
|
|
|
+
|
|
|
+ $this->info("Импортирую {$file} → {$database}");
|
|
|
+
|
|
|
+ $process = Process::fromShellCommandline($cmd);
|
|
|
+ $process->setTimeout(null);
|
|
|
+ $process->run(function ($type, $buffer) {
|
|
|
+ if ($type === Process::ERR) {
|
|
|
+ $this->getOutput()->write($buffer);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!$process->isSuccessful()) {
|
|
|
+ $this->error('Ошибка импорта: ' . $process->getErrorOutput());
|
|
|
+ return self::FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->info('Импорт завершён.');
|
|
|
+ return self::SUCCESS;
|
|
|
+ }
|
|
|
+}
|