From 76127de755bcc8d4d64ad754521a8f62180f7bf5 Mon Sep 17 00:00:00 2001 From: Jason McCreary Date: Tue, 11 Nov 2025 06:35:10 +1000 Subject: [PATCH 1/2] Configure default data types --- config/blueprint.php | 15 +++ src/Lexers/ModelLexer.php | 12 ++- tests/Feature/Lexers/ModelLexerTest.php | 138 ++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 2 deletions(-) diff --git a/config/blueprint.php b/config/blueprint.php index a533b8d8..c4256bf9 100644 --- a/config/blueprint.php +++ b/config/blueprint.php @@ -106,6 +106,21 @@ */ 'use_guarded' => false, + /* + |-------------------------------------------------------------------------- + | Default Data Types + |-------------------------------------------------------------------------- + | + | By default, Blueprint will set the primary key data type to `id` and the + | timestamps data type to `timestamp`. While you may customize these in + | your draft file, you may also configure your own defaults below. + | + */ + 'types' => [ + 'primary' => 'id', + 'timestamps' => 'timestamp', + ], + /* |-------------------------------------------------------------------------- | Singular route names diff --git a/src/Lexers/ModelLexer.php b/src/Lexers/ModelLexer.php index fadb2503..c655db0d 100644 --- a/src/Lexers/ModelLexer.php +++ b/src/Lexers/ModelLexer.php @@ -165,6 +165,10 @@ private function buildModel(string $name, array $columns): Model } elseif (isset($columns['timestampstz'])) { $model->enableTimestamps(true); unset($columns['timestampstz']); + } elseif (config('blueprint.types.timestamps') === false) { + $model->disableTimestamps(); + } else { + $model->enableTimestamps(strtolower(config('blueprint.types.timestamps')) === 'timestamptz'); } if (isset($columns['softdeletes'])) { @@ -203,8 +207,12 @@ private function buildModel(string $name, array $columns): Model } if (!isset($columns['id']) && $model->usesPrimaryKey()) { - $column = $this->buildColumn('id', 'id'); - $model->addColumn($column); + if (config('blueprint.types.primary')) { + $column = $this->buildColumn('id', config('blueprint.types.primary')); + $model->addColumn($column); + } else { + $model->disablePrimaryKey(); + } } foreach ($columns as $name => $definition) { diff --git a/tests/Feature/Lexers/ModelLexerTest.php b/tests/Feature/Lexers/ModelLexerTest.php index e98e5f1a..0d0051e2 100644 --- a/tests/Feature/Lexers/ModelLexerTest.php +++ b/tests/Feature/Lexers/ModelLexerTest.php @@ -3,6 +3,7 @@ namespace Tests\Feature\Lexers; use Blueprint\Lexers\ModelLexer; +use Illuminate\Support\Arr; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Tests\TestCase; @@ -124,6 +125,42 @@ public function it_defaults_the_id_column(): void $this->assertEquals(['nullable'], $columns['title']->modifiers()); } + #[Test] + public function it_defaults_the_id_column_based_on_configuration(): void + { + $type = Arr::random(['id', 'uuid', 'ulid']); + config(['blueprint.types.primary' => $type]); + + $tokens = [ + 'models' => [ + 'Model' => [ + 'title' => 'string nullable', + ], + ], + ]; + + $actual = $this->subject->analyze($tokens); + + $this->assertIsArray($actual['models']); + $this->assertCount(1, $actual['models']); + + $model = $actual['models']['Model']; + $this->assertEquals('Model', $model->name()); + $this->assertTrue($model->usesTimestamps()); + $this->assertFalse($model->usesSoftDeletes()); + + $columns = $model->columns(); + $this->assertCount(2, $columns); + $this->assertEquals('id', $columns['id']->name()); + $this->assertEquals($type, $columns['id']->dataType()); + $this->assertEquals([], $columns['id']->attributes()); + $this->assertEquals([], $columns['id']->modifiers()); + $this->assertEquals('title', $columns['title']->name()); + $this->assertEquals('string', $columns['title']->dataType()); + $this->assertEquals([], $columns['title']->attributes()); + $this->assertEquals(['nullable'], $columns['title']->modifiers()); + } + #[Test] public function it_disables_the_id_column(): void { @@ -147,6 +184,73 @@ public function it_disables_the_id_column(): void $this->assertFalse($model->usesPrimaryKey()); } + #[Test] + public function it_disables_the_id_column_based_on_configuration(): void + { + config(['blueprint.types.primary' => false]); + + $tokens = [ + 'models' => [ + 'Model' => [ + 'name' => 'string', + ], + ], + ]; + + $actual = $this->subject->analyze($tokens); + + $this->assertIsArray($actual['models']); + $this->assertCount(1, $actual['models']); + + $model = $actual['models']['Model']; + $this->assertEquals('Model', $model->name()); + $this->assertFalse($model->usesPrimaryKey()); + $this->assertCount(1, $model->columns()); + + $columns = $model->columns(); + $this->assertEquals('name', $columns['name']->name()); + $this->assertEquals('string', $columns['name']->dataType()); + $this->assertEquals([], $columns['name']->attributes()); + $this->assertEquals([], $columns['name']->modifiers()); + } + + #[Test] + public function it_sets_timestamps_data_type_based_on_configuration(): void + { + $type = Arr::random(['timestampTz', 'timestamptz']); + config(['blueprint.types.timestamps' => $type]); + + $tokens = [ + 'models' => [ + 'Model' => [ + 'name' => 'string', + ], + ], + ]; + + $actual = $this->subject->analyze($tokens); + + $this->assertIsArray($actual['models']); + $this->assertCount(1, $actual['models']); + + $model = $actual['models']['Model']; + $this->assertEquals('Model', $model->name()); + $this->assertTrue($model->usesTimestamps()); + $this->assertSame('timestampsTz', $model->timestampsDataType()); + $this->assertFalse($model->usesSoftDeletes()); + $this->assertCount(2, $model->columns()); + + $columns = $model->columns(); + $this->assertEquals('id', $columns['id']->name()); + $this->assertEquals('id', $columns['id']->dataType()); + $this->assertEquals([], $columns['id']->attributes()); + $this->assertEquals([], $columns['id']->modifiers()); + $this->assertEquals('name', $columns['name']->name()); + $this->assertEquals('string', $columns['name']->dataType()); + $this->assertEquals([], $columns['name']->attributes()); + $this->assertEquals([], $columns['name']->modifiers()); + } + #[Test] public function it_disables_timestamps(): void { @@ -169,6 +273,40 @@ public function it_disables_timestamps(): void $this->assertFalse($model->usesSoftDeletes()); } + #[Test] + public function it_disables_timestamps_based_on_configuration(): void + { + config(['blueprint.types.timestamps' => false]); + + $tokens = [ + 'models' => [ + 'Model' => [ + 'name' => 'string', + ], + ], + ]; + + $actual = $this->subject->analyze($tokens); + + $this->assertIsArray($actual['models']); + $this->assertCount(1, $actual['models']); + + $model = $actual['models']['Model']; + $this->assertEquals('Model', $model->name()); + $this->assertFalse($model->usesSoftDeletes()); + $this->assertCount(2, $model->columns()); + + $columns = $model->columns(); + $this->assertEquals('id', $columns['id']->name()); + $this->assertEquals('id', $columns['id']->dataType()); + $this->assertEquals([], $columns['id']->attributes()); + $this->assertEquals([], $columns['id']->modifiers()); + $this->assertEquals('name', $columns['name']->name()); + $this->assertEquals('string', $columns['name']->dataType()); + $this->assertEquals([], $columns['name']->attributes()); + $this->assertEquals([], $columns['name']->modifiers()); + } + #[Test] public function it_defaults_to_string_datatype(): void { From f9f648d51b4e11567fa6016a0c63c68b35127311 Mon Sep 17 00:00:00 2001 From: Jason McCreary Date: Tue, 11 Nov 2025 06:42:33 +1000 Subject: [PATCH 2/2] Default for backward compatibility --- src/Lexers/ModelLexer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Lexers/ModelLexer.php b/src/Lexers/ModelLexer.php index c655db0d..31927d9e 100644 --- a/src/Lexers/ModelLexer.php +++ b/src/Lexers/ModelLexer.php @@ -168,7 +168,7 @@ private function buildModel(string $name, array $columns): Model } elseif (config('blueprint.types.timestamps') === false) { $model->disableTimestamps(); } else { - $model->enableTimestamps(strtolower(config('blueprint.types.timestamps')) === 'timestamptz'); + $model->enableTimestamps(strtolower(config('blueprint.types.timestamps', 'timestamp')) === 'timestamptz'); } if (isset($columns['softdeletes'])) { @@ -208,7 +208,7 @@ private function buildModel(string $name, array $columns): Model if (!isset($columns['id']) && $model->usesPrimaryKey()) { if (config('blueprint.types.primary')) { - $column = $this->buildColumn('id', config('blueprint.types.primary')); + $column = $this->buildColumn('id', config('blueprint.types.primary', 'id')); $model->addColumn($column); } else { $model->disablePrimaryKey();