Fix: Make enum validation fail immediately instead of being caught by try-catch
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -98,8 +98,67 @@ class Constants_Regenerate_Command extends Command
|
|||||||
$enums = $reflector->getStaticPropertyValue('enums', []);
|
$enums = $reflector->getStaticPropertyValue('enums', []);
|
||||||
// We don't need 'rel' for constants generation
|
// We don't need 'rel' for constants generation
|
||||||
|
|
||||||
// Error check
|
// Error check - validate enum integrity BEFORE processing
|
||||||
|
// These checks run outside try-catch to fail immediately
|
||||||
foreach ($enums as $column => $enumValues) {
|
foreach ($enums as $column => $enumValues) {
|
||||||
|
// Validate enum values are integers
|
||||||
|
foreach ($enumValues as $value => $props) {
|
||||||
|
if (!is_int($value) && !ctype_digit((string)$value)) {
|
||||||
|
$this->error("Invalid enum value '{$value}' for column '{$column}' in model '{$fullClassName}'.");
|
||||||
|
$this->newLine();
|
||||||
|
$this->error("ENUM VALUES MUST BE INTEGERS.");
|
||||||
|
$this->newLine();
|
||||||
|
$this->line("The purpose of enum values is to store an INTEGER in the database that corresponds to a");
|
||||||
|
$this->line("string in the enum definition. The string label can then be changed in the enum 'label'");
|
||||||
|
$this->line("property without affecting the database value, so long as it continues to correspond to");
|
||||||
|
$this->line("the same numeric integer.");
|
||||||
|
$this->newLine();
|
||||||
|
$this->line("Example of a properly defined enum:");
|
||||||
|
$this->newLine();
|
||||||
|
$this->line(" protected static \$enums = [");
|
||||||
|
$this->line(" 'status' => [");
|
||||||
|
$this->line(" 1 => ['label' => 'Active', 'constant' => 'STATUS_ACTIVE'],");
|
||||||
|
$this->line(" 2 => ['label' => 'Inactive', 'constant' => 'STATUS_INACTIVE'],");
|
||||||
|
$this->line(" 3 => ['label' => 'Pending', 'constant' => 'STATUS_PENDING'],");
|
||||||
|
$this->line(" ],");
|
||||||
|
$this->line(" ];");
|
||||||
|
$this->newLine();
|
||||||
|
$this->line("For more information, run: php artisan rsx:man enums");
|
||||||
|
return 1; // Exit with error code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate enum column is integer type in database
|
||||||
|
$columnType = DB::getSchemaBuilder()->getColumnType($table, $column);
|
||||||
|
$validIntegerTypes = ['integer', 'bigint', 'smallint', 'tinyint', 'mediumint'];
|
||||||
|
|
||||||
|
if (!in_array($columnType, $validIntegerTypes)) {
|
||||||
|
$this->error("Invalid column type '{$columnType}' for enum column '{$column}' in table '{$table}' (model '{$fullClassName}').");
|
||||||
|
$this->newLine();
|
||||||
|
$this->error("ENUM COLUMNS MUST BE INTEGER TYPES.");
|
||||||
|
$this->newLine();
|
||||||
|
$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->newLine();
|
||||||
|
$this->line("Current column type: {$columnType}");
|
||||||
|
$this->line("Required column types: " . implode(', ', $validIntegerTypes));
|
||||||
|
$this->newLine();
|
||||||
|
$this->line("To fix this issue:");
|
||||||
|
$this->line("1. Create a migration to change the column type to an integer");
|
||||||
|
$this->line("2. Example migration:");
|
||||||
|
$this->newLine();
|
||||||
|
$this->line(" public function up()");
|
||||||
|
$this->line(" {");
|
||||||
|
$this->line(" Schema::table('{$table}', function (Blueprint \$table) {");
|
||||||
|
$this->line(" \$table->integer('{$column}')->change();");
|
||||||
|
$this->line(" });");
|
||||||
|
$this->line(" }");
|
||||||
|
$this->newLine();
|
||||||
|
$this->line("For more information, run: php artisan rsx:man enums");
|
||||||
|
return 1; // Exit with error code
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicate constants
|
||||||
$constants = [];
|
$constants = [];
|
||||||
foreach ($enumValues as $value => $props) {
|
foreach ($enumValues as $value => $props) {
|
||||||
if (isset($props['constant'])) {
|
if (isset($props['constant'])) {
|
||||||
@@ -141,58 +200,13 @@ class Constants_Regenerate_Command extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process enum magic methods and properties
|
// Process enum magic methods and properties
|
||||||
|
// Note: Validation already performed in early error check section above
|
||||||
foreach ($enums as $column => $enumValues) {
|
foreach ($enums as $column => $enumValues) {
|
||||||
// Validate that the database column is an integer type
|
|
||||||
$columnType = DB::getSchemaBuilder()->getColumnType($table, $column);
|
|
||||||
$validIntegerTypes = ['integer', 'bigint', 'smallint', 'tinyint', 'mediumint'];
|
|
||||||
|
|
||||||
if (!in_array($columnType, $validIntegerTypes)) {
|
|
||||||
throw new Exception(
|
|
||||||
"Invalid column type '{$columnType}' for enum column '{$column}' in table '{$table}' (model '{$fullClassName}').\n\n" .
|
|
||||||
"ENUM COLUMNS MUST BE INTEGER TYPES.\n\n" .
|
|
||||||
"Enum values are stored as integers in the database. The column must be defined as an " .
|
|
||||||
"integer type (INT, BIGINT, SMALLINT, TINYINT, or MEDIUMINT), not VARCHAR or other string types.\n\n" .
|
|
||||||
"Current column type: {$columnType}\n" .
|
|
||||||
"Required column types: " . implode(', ', $validIntegerTypes) . "\n\n" .
|
|
||||||
"To fix this issue:\n" .
|
|
||||||
"1. Create a migration to change the column type to an integer\n" .
|
|
||||||
"2. Example migration:\n\n" .
|
|
||||||
" public function up()\n" .
|
|
||||||
" {\n" .
|
|
||||||
" Schema::table('{$table}', function (Blueprint \$table) {\n" .
|
|
||||||
" \$table->integer('{$column}')->change();\n" .
|
|
||||||
" });\n" .
|
|
||||||
" }\n\n" .
|
|
||||||
"For more information, run: php artisan rsx:man enums"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$docblock .= " * @method static mixed {$column}_enum()\n";
|
$docblock .= " * @method static mixed {$column}_enum()\n";
|
||||||
$docblock .= " * @method static mixed {$column}_enum_select()\n";
|
$docblock .= " * @method static mixed {$column}_enum_select()\n";
|
||||||
$docblock .= " * @method static mixed {$column}_enum_ids()\n";
|
$docblock .= " * @method static mixed {$column}_enum_ids()\n";
|
||||||
$seenProps = [];
|
$seenProps = [];
|
||||||
foreach ($enumValues as $value => $props) {
|
foreach ($enumValues as $value => $props) {
|
||||||
// Validate that enum value is an integer
|
|
||||||
if (!is_int($value) && !ctype_digit((string)$value)) {
|
|
||||||
throw new Exception(
|
|
||||||
"Invalid enum value '{$value}' for column '{$column}' in model '{$fullClassName}'.\n\n" .
|
|
||||||
"ENUM VALUES MUST BE INTEGERS.\n\n" .
|
|
||||||
"The purpose of enum values is to store an INTEGER in the database that corresponds to a " .
|
|
||||||
"string in the enum definition. The string label can then be changed in the enum 'label' " .
|
|
||||||
"property without affecting the database value, so long as it continues to correspond to " .
|
|
||||||
"the same numeric integer.\n\n" .
|
|
||||||
"Example of a properly defined enum:\n\n" .
|
|
||||||
" protected static \$enums = [\n" .
|
|
||||||
" 'status' => [\n" .
|
|
||||||
" 1 => ['label' => 'Active', 'constant' => 'STATUS_ACTIVE'],\n" .
|
|
||||||
" 2 => ['label' => 'Inactive', 'constant' => 'STATUS_INACTIVE'],\n" .
|
|
||||||
" 3 => ['label' => 'Pending', 'constant' => 'STATUS_PENDING'],\n" .
|
|
||||||
" ],\n" .
|
|
||||||
" ];\n\n" .
|
|
||||||
"For more information, run: php artisan rsx:man enums"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($props as $p => $v) {
|
foreach ($props as $p => $v) {
|
||||||
if (!in_array($p, $seenProps)) {
|
if (!in_array($p, $seenProps)) {
|
||||||
$docblock .= " * @property-read mixed \${$column}_{$p}\n";
|
$docblock .= " * @property-read mixed \${$column}_{$p}\n";
|
||||||
|
|||||||
Reference in New Issue
Block a user