Fix enum column validation and migration data types
Remove numbered emoji and add no-emoji policy to CLAUDE.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -67,7 +67,7 @@ class Migrate_Begin_Command extends Command
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Step 1: Stop MySQL using supervisorctl
|
// Step 1: Stop MySQL using supervisorctl
|
||||||
$this->info('1️⃣ Stopping MySQL server...');
|
$this->info('[1] Stopping MySQL server...');
|
||||||
shell_exec('supervisorctl stop mysql 2>&1');
|
shell_exec('supervisorctl stop mysql 2>&1');
|
||||||
|
|
||||||
// Wait a moment for process to die
|
// Wait a moment for process to die
|
||||||
@@ -75,24 +75,24 @@ class Migrate_Begin_Command extends Command
|
|||||||
|
|
||||||
// Step 2: Remove old backup if exists
|
// Step 2: Remove old backup if exists
|
||||||
if (is_dir($this->backup_dir)) {
|
if (is_dir($this->backup_dir)) {
|
||||||
$this->info('2️⃣ Removing old backup...');
|
$this->info('[2] Removing old backup...');
|
||||||
$this->run_command(['rm', '-rf', $this->backup_dir]);
|
$this->run_command(['rm', '-rf', $this->backup_dir]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Copy MySQL data directory
|
// Step 3: Copy MySQL data directory
|
||||||
$this->info('3️⃣ Creating snapshot of MySQL data...');
|
$this->info('[3] Creating snapshot of MySQL data...');
|
||||||
$this->run_command(['cp', '-r', $this->mysql_data_dir, $this->backup_dir]);
|
$this->run_command(['cp', '-r', $this->mysql_data_dir, $this->backup_dir]);
|
||||||
|
|
||||||
// Step 4: Start MySQL again using supervisorctl
|
// Step 4: Start MySQL again using supervisorctl
|
||||||
$this->info('4️⃣ Starting MySQL server...');
|
$this->info('[4] Starting MySQL server...');
|
||||||
shell_exec('supervisorctl start mysql 2>&1');
|
shell_exec('supervisorctl start mysql 2>&1');
|
||||||
|
|
||||||
// Step 5: Wait for MySQL to be ready
|
// Step 5: Wait for MySQL to be ready
|
||||||
$this->info('5️⃣ Waiting for MySQL to be ready...');
|
$this->info('[5] Waiting for MySQL to be ready...');
|
||||||
$this->wait_for_mysql_ready();
|
$this->wait_for_mysql_ready();
|
||||||
|
|
||||||
// Step 6: Create migration flag file
|
// Step 6: Create migration flag file
|
||||||
$this->info('6️⃣ Creating migration flag...');
|
$this->info('[6] Creating migration flag...');
|
||||||
file_put_contents($this->flag_file, json_encode([
|
file_put_contents($this->flag_file, json_encode([
|
||||||
'started_at' => now()->toIso8601String(),
|
'started_at' => now()->toIso8601String(),
|
||||||
'started_by' => get_current_user(),
|
'started_by' => get_current_user(),
|
||||||
|
|||||||
@@ -87,12 +87,12 @@ class Migrate_Commit_Command extends Command
|
|||||||
try {
|
try {
|
||||||
// Step 1: Remove backup directory
|
// Step 1: Remove backup directory
|
||||||
if (is_dir($this->backup_dir)) {
|
if (is_dir($this->backup_dir)) {
|
||||||
$this->info('1️⃣ Removing backup snapshot...');
|
$this->info('[1] Removing backup snapshot...');
|
||||||
$this->run_command(['rm', '-rf', $this->backup_dir]);
|
$this->run_command(['rm', '-rf', $this->backup_dir]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Remove migration flag
|
// Step 2: Remove migration flag
|
||||||
$this->info('2️⃣ Removing migration flag...');
|
$this->info('[2] Removing migration flag...');
|
||||||
unlink($this->flag_file);
|
unlink($this->flag_file);
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
|
|||||||
@@ -41,37 +41,37 @@ class Migrate_Rollback_Command extends Command
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Step 1: Stop MySQL using supervisorctl
|
// Step 1: Stop MySQL using supervisorctl
|
||||||
$this->info('1️⃣ Stopping MySQL server...');
|
$this->info('[1] Stopping MySQL server...');
|
||||||
shell_exec('supervisorctl stop mysql 2>&1');
|
shell_exec('supervisorctl stop mysql 2>&1');
|
||||||
|
|
||||||
// Wait a moment for process to die
|
// Wait a moment for process to die
|
||||||
sleep(3);
|
sleep(3);
|
||||||
|
|
||||||
// Step 2: Clear current MySQL data
|
// Step 2: Clear current MySQL data
|
||||||
$this->info('2️⃣ Clearing current database data...');
|
$this->info('[2] Clearing current database data...');
|
||||||
// Use shell_exec to clear directory contents instead of removing directory
|
// Use shell_exec to clear directory contents instead of removing directory
|
||||||
shell_exec("rm -rf {$this->mysql_data_dir}/* 2>/dev/null");
|
shell_exec("rm -rf {$this->mysql_data_dir}/* 2>/dev/null");
|
||||||
shell_exec("rm -rf {$this->mysql_data_dir}/.* 2>/dev/null");
|
shell_exec("rm -rf {$this->mysql_data_dir}/.* 2>/dev/null");
|
||||||
|
|
||||||
// Step 3: Restore backup
|
// Step 3: Restore backup
|
||||||
$this->info('3️⃣ Restoring database snapshot...');
|
$this->info('[3] Restoring database snapshot...');
|
||||||
shell_exec("cp -r {$this->backup_dir}/* {$this->mysql_data_dir}/");
|
shell_exec("cp -r {$this->backup_dir}/* {$this->mysql_data_dir}/");
|
||||||
shell_exec("cp -r {$this->backup_dir}/.[^.]* {$this->mysql_data_dir}/ 2>/dev/null");
|
shell_exec("cp -r {$this->backup_dir}/.[^.]* {$this->mysql_data_dir}/ 2>/dev/null");
|
||||||
|
|
||||||
// Step 4: Fix permissions (MySQL needs to own the files)
|
// Step 4: Fix permissions (MySQL needs to own the files)
|
||||||
$this->info('4️⃣ Setting correct permissions...');
|
$this->info('[4] Setting correct permissions...');
|
||||||
$this->run_command(['chown', '-R', 'mysql:mysql', $this->mysql_data_dir]);
|
$this->run_command(['chown', '-R', 'mysql:mysql', $this->mysql_data_dir]);
|
||||||
|
|
||||||
// Step 5: Start MySQL using supervisorctl
|
// Step 5: Start MySQL using supervisorctl
|
||||||
$this->info('5️⃣ Starting MySQL server...');
|
$this->info('[5] Starting MySQL server...');
|
||||||
shell_exec('supervisorctl start mysql 2>&1');
|
shell_exec('supervisorctl start mysql 2>&1');
|
||||||
|
|
||||||
// Step 6: Wait for MySQL to be ready
|
// Step 6: Wait for MySQL to be ready
|
||||||
$this->info('6️⃣ Waiting for MySQL to be ready...');
|
$this->info('[6] Waiting for MySQL to be ready...');
|
||||||
$this->wait_for_mysql_ready();
|
$this->wait_for_mysql_ready();
|
||||||
|
|
||||||
// Step 7: Keep backup and flag - stay in migration mode
|
// Step 7: Keep backup and flag - stay in migration mode
|
||||||
$this->info('7️⃣ Rollback complete...');
|
$this->info('[7] Rollback complete...');
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
$this->info('');
|
$this->info('');
|
||||||
|
|||||||
@@ -132,19 +132,37 @@ class Constants_Regenerate_Command extends Command
|
|||||||
$columnType = DB::getSchemaBuilder()->getColumnType($table, $column);
|
$columnType = DB::getSchemaBuilder()->getColumnType($table, $column);
|
||||||
$validIntegerTypes = ['integer', 'bigint', 'smallint', 'tinyint', 'mediumint'];
|
$validIntegerTypes = ['integer', 'bigint', 'smallint', 'tinyint', 'mediumint'];
|
||||||
|
|
||||||
if (!in_array($columnType, $validIntegerTypes)) {
|
// Special case: allow 'boolean' type (TINYINT(1)) ONLY if enum values are 0 and 1
|
||||||
|
$isBooleanEnum = false;
|
||||||
|
if ($columnType === 'boolean') {
|
||||||
|
$enumKeys = array_keys($enumValues);
|
||||||
|
sort($enumKeys);
|
||||||
|
if ($enumKeys === [0, 1]) {
|
||||||
|
$isBooleanEnum = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($columnType, $validIntegerTypes) && !$isBooleanEnum) {
|
||||||
$this->error("Invalid column type '{$columnType}' for enum column '{$column}' in table '{$table}' (model '{$fullClassName}').");
|
$this->error("Invalid column type '{$columnType}' for enum column '{$column}' in table '{$table}' (model '{$fullClassName}').");
|
||||||
$this->newLine();
|
$this->newLine();
|
||||||
$this->error("ENUM COLUMNS MUST BE INTEGER TYPES.");
|
$this->error("ENUM COLUMNS MUST BE INTEGER TYPES.");
|
||||||
$this->newLine();
|
$this->newLine();
|
||||||
|
|
||||||
|
// Special message for boolean/TINYINT
|
||||||
|
if ($columnType === 'boolean') {
|
||||||
|
$this->line("TINYINT columns are reported as 'boolean' by Laravel because TINYINT is ONLY for true/false values.");
|
||||||
|
$this->line("For enum values with multiple options (1, 2, 3, etc.), you MUST use INT or BIGINT.");
|
||||||
|
$this->newLine();
|
||||||
|
}
|
||||||
|
|
||||||
$this->line("Enum values are stored as integers in the database. The column must be defined as an");
|
$this->line("Enum values are stored as integers in the database. The column must be defined as an");
|
||||||
$this->line("integer type (INT, BIGINT, SMALLINT, TINYINT, or MEDIUMINT), not VARCHAR or other string types.");
|
$this->line("integer type (INT, BIGINT, SMALLINT, or MEDIUMINT), not VARCHAR, TINYINT, or other types.");
|
||||||
$this->newLine();
|
$this->newLine();
|
||||||
$this->line("Current column type: {$columnType}");
|
$this->line("Current column type: {$columnType}");
|
||||||
$this->line("Required column types: " . implode(', ', $validIntegerTypes));
|
$this->line("Required column types: " . implode(', ', $validIntegerTypes));
|
||||||
$this->newLine();
|
$this->newLine();
|
||||||
$this->line("To fix this issue:");
|
$this->line("To fix this issue:");
|
||||||
$this->line("1. Create a migration to change the column type to an integer");
|
$this->line("1. Create a migration to change the column type to INT or BIGINT");
|
||||||
$this->line("2. Example migration:");
|
$this->line("2. Example migration:");
|
||||||
$this->newLine();
|
$this->newLine();
|
||||||
$this->line(" public function up()");
|
$this->line(" public function up()");
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ return new class extends Migration
|
|||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
// Add status column (1=active, 2=inactive, 3=suspended)
|
// Add status column (1=active, 2=inactive, 3=suspended)
|
||||||
DB::statement("ALTER TABLE users ADD COLUMN status TINYINT NOT NULL DEFAULT 1 AFTER is_verified");
|
DB::statement("ALTER TABLE users ADD COLUMN status INT NOT NULL DEFAULT 1 AFTER is_verified");
|
||||||
DB::statement("ALTER TABLE users ADD INDEX idx_status (status)");
|
DB::statement("ALTER TABLE users ADD INDEX idx_status (status)");
|
||||||
|
|
||||||
// Add user_role_id column (1=read_only, 2=standard, 3=admin, 4=billing_admin, 5=root_admin)
|
// Add user_role_id column (1=read_only, 2=standard, 3=admin, 4=billing_admin, 5=root_admin)
|
||||||
DB::statement("ALTER TABLE users ADD COLUMN user_role_id TINYINT NOT NULL DEFAULT 2 AFTER status");
|
DB::statement("ALTER TABLE users ADD COLUMN user_role_id INT NOT NULL DEFAULT 2 AFTER status");
|
||||||
DB::statement("ALTER TABLE users ADD INDEX idx_user_role_id (user_role_id)");
|
DB::statement("ALTER TABLE users ADD INDEX idx_user_role_id (user_role_id)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ return new class extends Migration
|
|||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
// Rename status column to status_id to match enum naming convention
|
// Rename status column to status_id to match enum naming convention
|
||||||
DB::statement("ALTER TABLE users CHANGE COLUMN status status_id TINYINT NOT NULL DEFAULT 1");
|
DB::statement("ALTER TABLE users CHANGE COLUMN status status_id INT NOT NULL DEFAULT 1");
|
||||||
|
|
||||||
// Recreate the index with the new column name
|
// Recreate the index with the new column name
|
||||||
DB::statement("ALTER TABLE users DROP INDEX idx_status");
|
DB::statement("ALTER TABLE users DROP INDEX idx_status");
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ return new class extends Migration
|
|||||||
name VARCHAR(255) NOT NULL,
|
name VARCHAR(255) NOT NULL,
|
||||||
description TEXT,
|
description TEXT,
|
||||||
price DECIMAL(10,2) NOT NULL,
|
price DECIMAL(10,2) NOT NULL,
|
||||||
status_id TINYINT NOT NULL DEFAULT 1,
|
status_id INT NOT NULL DEFAULT 1,
|
||||||
category_id TINYINT NOT NULL DEFAULT 1,
|
category_id INT NOT NULL DEFAULT 1,
|
||||||
created_at TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3),
|
created_at TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3),
|
||||||
updated_at TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
updated_at TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||||
INDEX idx_status_id (status_id),
|
INDEX idx_status_id (status_id),
|
||||||
|
|||||||
Reference in New Issue
Block a user