A foreign key's implicit index breaks dropping its column after introspection
Author: morozovCreated Jul 26, 2026Updated Aug 26, 2026
LabelsSchema DefinitionForeign KeysIndexes
| Q | A |
|---|---|
| Version | 4.4.x |
Table fabricates an implicit index to back a foreign key and records its name in $implicitIndexNames. On a constructed table the index is implicit, so dropping the foreign key drops it too. A round-trip through the database breaks that in two steps:
- Create-and-introspect loses the index's implicitness. The database has no notion of an implicit index, so introspection brings it back as an explicit one.
- Dropping the foreign key does not automatically drop the no longer implicit index. Dropping its column then leaves an index over a column that doesn't exist, so the table is invalid.
Given child(id PK, parent_id) with a foreign key child_parent on parent_id referencing parent(id), where the invalid table is caught depends on how it's edited:
The mutable
TableAPI has no build-time check, so the invalid table reaches the database on drop-and-create:$child = $schemaManager->introspectTableByUnquotedName('child'); $child->removeForeignKey('child_parent'); $child->dropColumn('parent_id'); $schemaManager->dropTable('child'); $schemaManager->createTable($child); // DriverException: SQLSTATE[HY000]: General error: 1 no such column: parent_idThe editor rejects it earlier, when
create()builds the object:$child = $schemaManager->introspectTableByUnquotedName('child'); $child->edit() ->dropColumnByUnquotedName('parent_id') ->dropForeignKeyConstraintByUnquotedName('child_parent') ->create(); // ColumnDoesNotExist: There is no column with name "parent_id" on table child.
Source: doctrine/dbal