diff --git a/src/Generators/MigrationGenerator.php b/src/Generators/MigrationGenerator.php index 46146572..0c9691fa 100644 --- a/src/Generators/MigrationGenerator.php +++ b/src/Generators/MigrationGenerator.php @@ -320,7 +320,7 @@ protected function buildForeignKey(string $column_name, ?string $on, string $typ $on_update_suffix = '->cascadeOnUpdate()'; } - if ($column_name === Str::singular($table) . '_' . $column) { + if ($column_name === Str::singular($table) . '_' . $column && !Str::contains($column, '_')) { return self::INDENT . "{$prefix}->constrained(){$on_delete_suffix}{$on_update_suffix}"; } diff --git a/tests/Feature/Generators/MigrationGeneratorTest.php b/tests/Feature/Generators/MigrationGeneratorTest.php index db60ae3c..a8f577cb 100644 --- a/tests/Feature/Generators/MigrationGeneratorTest.php +++ b/tests/Feature/Generators/MigrationGeneratorTest.php @@ -613,6 +613,43 @@ public function output_generates_custom_pivot_tables(): void $this->assertEquals(['created' => [$user_migration, $team_migration, $pivot_migration]], $this->subject->output($tree)); } + #[Test] + public function output_creates_constraint_for_foreign_key_to_non_id_column_with_underscore(): void + { + $this->app->config->set('blueprint.use_constraints', true); + + $this->filesystem->expects('stub') + ->with('migration.stub') + ->andReturn($this->stub('migration.stub')); + + $now = Carbon::now(); + Carbon::setTestNow($now); + + $agent_path = str_replace( + 'timestamp', + $now->copy()->subSecond()->format('Y_m_d_His'), + 'database/migrations/timestamp_create_agents_table.php' + ); + + $employment_path = str_replace( + 'timestamp', + $now->format('Y_m_d_His'), + 'database/migrations/timestamp_create_employments_table.php' + ); + + $this->filesystem->expects('exists')->times(2)->andReturn(false); + + $this->filesystem->expects('put') + ->with($agent_path, $this->fixture('migrations/foreign-key-underscore-agents.php')); + $this->filesystem->expects('put') + ->with($employment_path, $this->fixture('migrations/foreign-key-underscore.php')); + + $tokens = $this->blueprint->parse($this->fixture('drafts/foreign-key-underscore.yaml')); + $tree = $this->blueprint->analyze($tokens); + + $this->assertEquals(['created' => [$agent_path, $employment_path]], $this->subject->output($tree)); + } + public static function modelTreeDataProvider() { return [ diff --git a/tests/fixtures/drafts/foreign-key-underscore.yaml b/tests/fixtures/drafts/foreign-key-underscore.yaml new file mode 100644 index 00000000..235f1c95 --- /dev/null +++ b/tests/fixtures/drafts/foreign-key-underscore.yaml @@ -0,0 +1,10 @@ +models: + + Agent: + id: false + party_id: id + + Employment: + id: false + # Referencing agents.party_id (custom column, has underscore) + agent_party_id: id foreign:agents.party_id \ No newline at end of file diff --git a/tests/fixtures/migrations/foreign-key-underscore-agents.php b/tests/fixtures/migrations/foreign-key-underscore-agents.php new file mode 100644 index 00000000..e113c7ad --- /dev/null +++ b/tests/fixtures/migrations/foreign-key-underscore-agents.php @@ -0,0 +1,31 @@ +foreignId('party_id')->constrained()->cascadeOnDelete()->cascadeOnUpdate(); + $table->timestamps(); + }); + + Schema::enableForeignKeyConstraints(); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('agents'); + } +}; diff --git a/tests/fixtures/migrations/foreign-key-underscore.php b/tests/fixtures/migrations/foreign-key-underscore.php new file mode 100644 index 00000000..69d49fd9 --- /dev/null +++ b/tests/fixtures/migrations/foreign-key-underscore.php @@ -0,0 +1,31 @@ +foreignId('agent_party_id')->constrained('agents', 'party_id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->timestamps(); + }); + + Schema::enableForeignKeyConstraints(); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('employments'); + } +};