0043. An enforced morph map with stable aliases for polymorphic types
Generated from docs/decisions/0043-enforced-morph-map.md
- Status: Proposed
- Date: 2026-10-09
- Plan:
docs/plans/leftovers-0-2.md(L0-10)
Context and problem statement
Section titled “Context and problem statement”Polymorphic columns store PHP class names: topics.topicable_type, notifications, tags, cart and
payments, model fields, Spatie role and permission tables, and others. The 2026 rename from
EscolaLms\ to Ulams\ needed a data migration that rewrote every such column, and every future
class rename would need the same. The admin, the SDK and the Astro front also compare class-name
strings.
Considered options
Section titled “Considered options”Relation::enforceMorphMapwith stable snake-case aliases, plus a data migration.- A non-enforced
morphMap(aliases optional). - Keep class names.
Decision
Section titled “Decision”Option 1:
- Registration. Packages register aliases with
MorphMap::register()in their providers, and the app callsenforceMorphMaponce all providers have booted. - Alias names. Topic contents use
topic.<type>. Other models use their singular names (course,user,product, …). - Data migration. A per-tenant migration (run by
ulams:upgrade) rewrites existing values. - API compatibility. Topic resources return the alias in
topicable_type, plus a deprecatedtopicable_classfor one release. Requests and course imports accept both forms.
Consequences
Section titled “Consequences”- Good: class renames never orphan data, and clients compare short stable strings.
- Bad: one broad PR touching the API, admin and SDK together, and a data migration in every tenant.
- Bad: external API consumers must switch to aliases within one release.