Skip to content

Commit eca7f43

Browse files
Karim-Ashrafcursoragent
authored andcommitted
Fix int/bool/bigint field type aliases in FieldParser
parent_id:int was rejected because int was only treated as an enum backing. Resolve int/bool/bigint as integer/boolean/biginteger, and treat int/string as enum backings only after enum. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent c4b120a commit eca7f43

4 files changed

Lines changed: 45 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.4.1] - 2026-07-22
11+
12+
### Fixed
13+
14+
- Field parser treated `int` as an enum backing everywhere, so definitions like `parent_id:int` failed. `int` / `bool` / `bigint` are now type aliases (`integer` / `boolean` / `biginteger`); `int`/`string` are enum backings only after `enum` (e.g. `status:enum:int`).
15+
1016
## [1.4.0] - 2026-07-22
1117

1218
### Added
@@ -106,7 +112,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
106112
- Support for Laravel 11, 12 and 13 (PHP 8.2 – 8.5, per framework requirements).
107113
- Full test suite (PHPUnit via Orchestra Testbench), PHPStan level 5 (Larastan) and Laravel Pint.
108114

109-
[Unreleased]: https://github.com/gubakareem/lara-architect/compare/v1.4.0...HEAD
115+
[Unreleased]: https://github.com/gubakareem/lara-architect/compare/v1.4.1...HEAD
116+
[1.4.1]: https://github.com/gubakareem/lara-architect/releases/tag/v1.4.1
110117
[1.4.0]: https://github.com/gubakareem/lara-architect/releases/tag/v1.4.0
111118
[1.3.0]: https://github.com/gubakareem/lara-architect/releases/tag/v1.3.0
112119
[1.2.0]: https://github.com/gubakareem/lara-architect/releases/tag/v1.2.0

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ php artisan architect:patterns
176176
name:string, price:decimal, sku:string:unique, published_at:datetime:nullable, meta:json:nullable
177177
```
178178

179-
Supported types: `string`, `text`, `integer`, `biginteger`, `boolean`, `decimal`, `float`, `date`, `datetime`, `json`, `uuid`, `foreignid`, `enum`. Modifiers: `nullable`, `unique`. For enums, add a backing type: `status:enum` (string) or `status:enum:int` (integer).
179+
Supported types: `string`, `text`, `integer` (alias `int`), `biginteger` (alias `bigint`), `boolean` (alias `bool`), `decimal`, `float`, `date`, `datetime`, `json`, `uuid`, `foreignid`, `enum`. Modifiers: `nullable`, `unique`. For enums, add a backing type: `status:enum` (string) or `status:enum:int` (integer).
180180

181181
A unique field automatically gets `Rule::unique(...)` in the store request and `Rule::unique(...)->ignore($this->route(...))` in the update request.
182182

src/Generation/FieldParser.php

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,24 @@
1010
/**
1111
* Parses the --fields option syntax:
1212
*
13-
* name:string, price:decimal:nullable, status:enum:int, sku:string:unique
13+
* name:string, price:decimal:nullable, status:enum:int, parent_id:int
1414
*
15-
* Segments after the type are modifiers (nullable, unique, required) or, for
16-
* enum fields, a backing type (string|int — defaults to string).
15+
* Segments after the name are a type (or alias like int→integer), then
16+
* modifiers (nullable, unique, required). For enum fields, string|int
17+
* after `enum` sets the backing type (defaults to string).
1718
*/
1819
final class FieldParser
1920
{
2021
private const MODIFIERS = ['nullable', 'unique', 'required'];
2122

2223
private const ENUM_BACKINGS = ['string', 'int'];
2324

25+
private const TYPE_ALIASES = [
26+
'int' => 'integer',
27+
'bool' => 'boolean',
28+
'bigint' => 'biginteger',
29+
];
30+
2431
/**
2532
* @return list<Field>
2633
*/
@@ -58,29 +65,25 @@ private static function parseField(string $segment): Field
5865
continue;
5966
}
6067

61-
if (in_array($lower, self::ENUM_BACKINGS, true)) {
68+
// `status:enum:int` — int/string after enum is the backing type,
69+
// not a field-type rewrite of the already-chosen enum.
70+
if ($type === 'enum' && in_array($lower, self::ENUM_BACKINGS, true)) {
6271
$enumBacking = $lower;
6372

6473
continue;
6574
}
6675

67-
if (! Field::isSupportedType($lower)) {
76+
$resolved = self::TYPE_ALIASES[$lower] ?? $lower;
77+
78+
if (! Field::isSupportedType($resolved)) {
6879
throw new InvalidArgumentException(sprintf(
6980
'Unknown field type or modifier [%s] for field [%s].',
7081
$part,
7182
$name,
7283
));
7384
}
7485

75-
$type = $lower;
76-
}
77-
78-
if ($enumBacking !== 'string' && $type !== 'enum') {
79-
throw new InvalidArgumentException(sprintf(
80-
'Backing type [%s] is only valid for enum fields (field [%s]).',
81-
$enumBacking,
82-
$name,
83-
));
86+
$type = $resolved;
8487
}
8588

8689
return new Field(

tests/Unit/FieldParserTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,25 @@ public function test_int_backed_enum_fields_are_supported(): void
7474
], $fields[0]->enumCases());
7575
}
7676

77+
public function test_int_bool_and_bigint_are_type_aliases(): void
78+
{
79+
$fields = FieldParser::parse('parent_id:int, active:bool, views:bigint');
80+
81+
$this->assertSame('integer', $fields[0]->type);
82+
$this->assertSame('boolean', $fields[1]->type);
83+
$this->assertSame('biginteger', $fields[2]->type);
84+
}
85+
86+
public function test_int_after_enum_is_backing_not_integer_type(): void
87+
{
88+
$fields = FieldParser::parse('name:json,parent_id:int,status:enum:int,order:int');
89+
90+
$this->assertSame('json', $fields[0]->type);
91+
$this->assertSame('integer', $fields[1]->type);
92+
$this->assertTrue($fields[2]->isIntEnum());
93+
$this->assertSame('integer', $fields[3]->type);
94+
}
95+
7796
public function test_field_produces_migration_column_and_rules(): void
7897
{
7998
$field = new Field(name: 'price', type: 'decimal', nullable: true);

0 commit comments

Comments
 (0)