About doctrine-relations
A Symfony and Doctrine skill for mapping entity relations and managing their persistence behavior. It guides owning-side decisions, cascading, orphan removal, collection loading, and multiple entity managers.
Key features
- 01Map owning and inverse sides
- 02Keep bidirectional collections in sync
- 03Choose cascade and orphan removal
- 04Handle large collections and fetch joins
- 05Work with multiple entity managers
Use cases
- 01Map a new Doctrine relation
- 02Fix relations that do not persist
- 03Choose removal behavior for child entities
- 04Access repositories across entity managers
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ dev-toolings/ superpowers-symfony --skill doctrine-relationsAfter installing, type/doctrine-relationsin Claude Code to confirm it loaded.
Bundled filesreference.md
Details
From the project READMEDoctrine Relations (Symfony)
Use when
- Mapping a
ManyToOne,OneToMany,ManyToManyorOneToOneand choosing the owning side. - Deciding between
cascadeandorphanRemovalfor child entities. - A relation does not persist (only the inverse side was set), or
contains()is slow on a large inverse collection. - Splitting entities across several entity managers.
Default workflow
- Pick the owning side (holds the foreign key,
ManyToOnewithinversedBy) and the inverse side (OneToManywithmappedBy). - Initialize collections with
ArrayCollectionin the constructor, and writeaddX()andremoveX()helpers that keep both sides in sync. - Use
cascade: ['persist']for aggregates saved together, andorphanRemoval: trueonly for true composition. - Mark large inverse collections
fetch: 'EXTRA_LAZY', or test membership from the owning side. - Add fetch joins where a use case reads the relation, to avoid N+1 queries.
- With several entity managers, keep each entity set in one manager and fetch repositories through
ManagerRegistry.
Guardrails
- Doctrine persists what the owning side holds: always set the
ManyToOnereference. - Avoid
cascade: ['remove']on large collections (one DELETE per row), and never useorphanRemovalon shared entities. - A relation cannot span two entity managers.
- For a non-default entity manager, fetch repositories with
ManagerRegistry::getRepository(Entity::class, 'name').
Progressive disclosure
- Use this file for execution posture and risk controls.
- Open references when deep implementation details are needed.
Output contract
- Entity mappings with the owning and inverse sides, cascade and orphan decisions.
- Fetch strategy for large collections and hot paths.
- Result of
doctrine:schema:validate.
References
reference.md
Comments
Markdown supported