Skip to content

Skip self-referencing associations for unconstrained keys#1094

Merged
dereuromark merged 1 commit into
3.xfrom
fix-1092-skip-self-associations
Jun 15, 2026
Merged

Skip self-referencing associations for unconstrained keys#1094
dereuromark merged 1 commit into
3.xfrom
fix-1092-skip-self-associations

Conversation

@dereuromark

Copy link
Copy Markdown
Member

Addresses #1092

Problem

When a column follows the <table>_id naming on its own table - for example an external system_id on a systems table that is not a real foreign key - bake derived the alias Systems for both the generated belongsTo (from the column) and the self-referencing hasMany/hasOne detection. Applying the second association threw and aborted the whole bake run:

[Cake\Core\Exception\CakeException] Association alias `Systems` is already set.

Per the discussion in #1092 (cc the maintainer thread), legitimate self-references conventionally use parent_id, which already gets dedicated Parent*/Child* aliases. A plain <table>_id that is not backed by a foreign key is almost always an external identifier, not a self-association.

Fix

Skip generating a self-referencing association when the resolved alias equals the table's own alias and the column is not actually constrained as a foreign key to that table. The guard is applied consistently across all three detection passes:

  • findBelongsTo() - skip the column unless findTableReferencedBy() confirms a real constraint.
  • findHasMany() - skip self-table matches (the parent_id self-ref keeps its existing Child* handling).
  • findHasOne() - skip self-table matches for unique columns.

Real, constrained self-references (a node_id foreign key referencing nodes.id) still produce their belongsTo, so no valid association is lost.

Relationship to #1093

This is the upstream prevention (do not generate the bogus association). #1093 is independent downstream hardening (never fatal on a duplicate alias from any other cause). They compose and do not conflict.

A column following the `<table>_id` naming on its own table (such as an
external `system_id` on a `systems` table) made bake generate a
self-referencing association whose alias equals the table's own name.
The generated belongsTo and hasMany/hasOne then collided, and applying
them threw "Association alias `Systems` is already set", aborting the
bake run.

Self-references are now only generated when the column is actually
constrained as a foreign key to the same table. Legitimate self-refs
such as `parent_id` keep their existing dedicated aliases, while
convention-only `<table>_id` columns without a real constraint are
skipped across the belongsTo, hasOne and hasMany detection passes.
@dereuromark dereuromark merged commit a56cd81 into 3.x Jun 15, 2026
9 checks passed
@dereuromark dereuromark deleted the fix-1092-skip-self-associations branch June 15, 2026 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants