Skip to content

feat: extend existing entity tables via #[Table(extends:)]#64

Merged
markshust merged 1 commit into
developfrom
feature/table-extension
May 12, 2026
Merged

feat: extend existing entity tables via #[Table(extends:)]#64
markshust merged 1 commit into
developfrom
feature/table-extension

Conversation

@markshust
Copy link
Copy Markdown
Collaborator

Summary

  • Any module can add columns to another module's entity table without touching the original entity class
  • Declare #[Table(extends: ParentEntity::class)] on a plain Entity subclass — its columns/indexes/foreign-keys merge into the parent's table schema
  • The extender hydrates from the same row as a companion on the parent; Repository::save() persists parent + companion data in a single INSERT/UPDATE
  • Supersedes feat(entity-extension): add entity extension system #59 with a much smaller surface (~700 LOC vs ~3.3k) by reusing the existing Entity pipeline instead of building a parallel EntityExtension hierarchy

Highlights

  • New Entity APIs: companions(), companion(class) (typed via @template), attachCompanion()
  • SchemaRegistry::registerEntities() is two-pass: parses all, then merges each parent's table with linked extenders
  • Loud validation at parse/register time for: chained extension, redeclared PK, autoIncrement on extenders, duplicate column/index names (both class-strings in the error message)
  • Rolling-deploy safe: extender hydration silently skipped when columns aren't yet migrated
  • Repository safety guards: rejects extender ENTITY_CLASS at construct; rejects insertBatch() when entities have companions attached
  • migrate:diff sees the merged table — no extra code needed for schema migrations

Test plan

  • 5136 tests pass, 0 failures (full composer test suite)
  • 8 new task-level test files cover attribute, metadata, factory, registry, hydrator, repository, integration
  • End-to-end integration test against in-memory SQLite proves: schema merge, single-INSERT/UPDATE, rolling-deploy skip, discovery integration, both safety guards
  • Docs page updated with usage, rules, schema merging, and rolling-deploy behavior

Closes #63

🤖 Generated with Claude Code

Any module can now add columns to another module's entity table without
touching the original entity class. Declare a plain Entity subclass with
#[Table(extends: ParentEntity::class)] — the framework merges its
columns/indexes/foreign-keys into the parent's table schema and hydrates
the extender from the same row as a companion on the parent entity.

Closes #63
Supersedes #59

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the enhancement New feature or request label May 12, 2026
@markshust markshust merged commit 1d9793a into develop May 12, 2026
1 check passed
@markshust markshust deleted the feature/table-extension branch May 12, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: extend existing entity tables via #[Table(extends:)]

1 participant