Song 調整歌曲名稱滙入錯誤問題
加入 sqllitToMysql 20250510
This commit is contained in:
parent
580f3c7f9b
commit
75e41c43ef
76
app/Console/Commands/TransferSqliteToMysql.php
Normal file
76
app/Console/Commands/TransferSqliteToMysql.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
class TransferSqliteToMysql extends Command
|
||||
{
|
||||
protected $signature = 'transfer:sqlite-to-mysql';
|
||||
|
||||
protected $description = 'Transfer all data from SQLite to MySQL, optionally truncating tables first.';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
// ✅ 自訂 SQLite 連線路徑(請修改為你實際的檔案位置)
|
||||
Config::set('database.connections.sqlite', [
|
||||
'driver' => 'sqlite',
|
||||
'database' => base_path('database/database.sqlite'),
|
||||
'prefix' => '',
|
||||
]);
|
||||
|
||||
$this->info("🚀 Starting transfer from SQLite to MySQL...");
|
||||
|
||||
// 讀取 SQLite 資料庫的所有資料表
|
||||
$sqliteTables = DB::connection('sqlite')->select("
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name NOT LIKE 'sqlite_%';
|
||||
");
|
||||
|
||||
if (empty($sqliteTables)) {
|
||||
$this->error("❌ No tables found in SQLite database.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 取得 .env 中指定的 MySQL 連線名稱
|
||||
$mysqlConnection = config('database.default'); // 默認會是 'mysql',如果 .env 修改會自動更新
|
||||
|
||||
foreach ($sqliteTables as $tableObj) {
|
||||
$table = $tableObj->name;
|
||||
|
||||
// 忽略 Laravel 內部 migration 表
|
||||
if ($table === 'migrations') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->info("📦 Transferring table: {$table}");
|
||||
|
||||
try {
|
||||
// 從 SQLite 資料庫讀取資料
|
||||
$records = DB::connection('sqlite')->table($table)->get();
|
||||
|
||||
if ($records->isEmpty()) {
|
||||
$this->warn("⚠️ Table {$table} has no data.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 資料分批處理,避免一次插入過多資料造成效能問題
|
||||
$chunks = $records->chunk(500);
|
||||
foreach ($chunks as $chunk) {
|
||||
DB::connection($mysqlConnection)->table($table)->insert(
|
||||
$chunk->map(fn ($row) => (array) $row)->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
$this->info("✅ Done: {$table}");
|
||||
} catch (\Exception $e) {
|
||||
$this->error("❌ Failed to transfer {$table}: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$this->info("🎉 Transfer complete!");
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -24,23 +24,23 @@ class ImportArtistChunkJob implements ShouldQueue
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$artists = collect();
|
||||
|
||||
foreach ($this->rows as $index => $row) {
|
||||
try {
|
||||
$name = trim($row['歌手姓名'] ?? '');
|
||||
|
||||
if (empty($name)) {
|
||||
continue;
|
||||
}
|
||||
if (Artist::where('name', $name)->exists()) {
|
||||
if (empty($name) || Artist::where('name', $name)->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Artist::create([
|
||||
$artist = new Artist([
|
||||
'name' => $name,
|
||||
'category' => ArtistCategory::tryFrom(trim($row['歌手分類'] ?? '未定義')) ?? ArtistCategory::Unset,
|
||||
'enable' => trim($row['狀態'] ?? 1),
|
||||
]);
|
||||
|
||||
$artists->push($artist);
|
||||
} catch (\Throwable $e) {
|
||||
\Log::error("Row {$index} failed: {$e->getMessage()}", [
|
||||
'row' => $row,
|
||||
@ -48,5 +48,6 @@ class ImportArtistChunkJob implements ShouldQueue
|
||||
]);
|
||||
}
|
||||
}
|
||||
$artists->each(fn ($artist) => $artist->save());
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@ class ImportSongChunkJob implements ShouldQueue
|
||||
// 準備 song 資料
|
||||
$song = new Song([
|
||||
'id' => $songId,
|
||||
'name' => trim($row['歌名'] ?? ''),
|
||||
'name' => $this->formatText($row['歌名']),
|
||||
'adddate' => $this->parseExcelDate($row['日期'] ?? null),
|
||||
'filename' => trim($row['檔名'] ?? ''),
|
||||
'language_type' => SongLanguageType::tryFrom(trim($row['語別'] ?? '')) ?? SongLanguageType::Unset,
|
||||
@ -113,6 +113,16 @@ class ImportSongChunkJob implements ShouldQueue
|
||||
|
||||
return $this->artistCache[$name] = $artist->id;
|
||||
}
|
||||
protected function formatText($value)
|
||||
{
|
||||
if (is_numeric($value) && $value < 1 && $value > 0) {
|
||||
// 嘗試判斷為時間類型的小數,轉為時間字串
|
||||
$time = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);
|
||||
return $time->format('H:i');
|
||||
}
|
||||
|
||||
return trim((string) $value);
|
||||
}
|
||||
private function parseExcelDate($value): ?string
|
||||
{
|
||||
if (is_numeric($value)) {
|
||||
|
@ -45,7 +45,7 @@ class Artist extends Model
|
||||
|
||||
$chars = preg_split('//u', $artist->name, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$firstChar = $chars[0] ?? null;
|
||||
$artist->strokes_abbr=$firstChar ? ChineseStrokesConverter::getStrokes($firstChar) : null;
|
||||
$artist->strokes_abbr=( $firstChar && preg_match('/\p{Han}/u', $firstChar) ) ? ChineseStrokesConverter::getStrokes($firstChar) : 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,8 @@ class Song extends Model
|
||||
|
||||
$chars = preg_split('//u', $song->name, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$firstChar = $chars[0] ?? null;
|
||||
$song->strokes_abbr=$firstChar ? ChineseStrokesConverter::getStrokes($firstChar) : null;
|
||||
|
||||
$song->strokes_abbr=($firstChar && preg_match('/\p{Han}/u', $firstChar)) ? ChineseStrokesConverter::getStrokes($firstChar) : 0;
|
||||
$song->song_number = mb_strlen($song->name, 'UTF-8');
|
||||
});
|
||||
}
|
||||
|
BIN
database/.DS_Store
vendored
BIN
database/.DS_Store
vendored
Binary file not shown.
@ -16,8 +16,8 @@ return new class extends Migration
|
||||
$table->string('queue')->index();
|
||||
$table->longText('payload');
|
||||
$table->unsignedTinyInteger('attempts');
|
||||
$table->unsignedInteger('reserved_at')->nullable();
|
||||
$table->unsignedInteger('available_at');
|
||||
$table->timestamp('reserved_at')->nullable();
|
||||
$table->timestamp('available_at');
|
||||
$table->unsignedInteger('created_at');
|
||||
});
|
||||
|
||||
@ -29,9 +29,9 @@ return new class extends Migration
|
||||
$table->integer('failed_jobs');
|
||||
$table->longText('failed_job_ids');
|
||||
$table->mediumText('options')->nullable();
|
||||
$table->integer('cancelled_at')->nullable();
|
||||
$table->integer('created_at');
|
||||
$table->integer('finished_at')->nullable();
|
||||
$table->timestamp('cancelled_at')->nullable();
|
||||
$table->timestamp('created_at');
|
||||
$table->timestamp('finished_at')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('failed_jobs', function (Blueprint $table) {
|
||||
|
BIN
storage/.DS_Store
vendored
BIN
storage/.DS_Store
vendored
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user