About doctrine-fetch-modes
A Symfony and Doctrine skill for choosing fetch strategies and shaping read queries. It covers reducing N+1 queries and over-fetching with fetch joins, DTO projections, and DBAL 4 methods.
Key features
- 01Diagnose N+1 queries
- 02Choose relation fetch modes
- 03Use fetch joins for required data
- 04Project read results into DTOs
- 05Apply DBAL 4 query methods
Use cases
- 01Fix list endpoints with N+1 queries
- 02Load only needed fields for read-only lists
- 03Choose fetch behavior for large collections
- 04Write report queries with DBAL 4
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ dev-toolings/ superpowers-symfony --skill doctrine-fetch-modesAfter installing, type/doctrine-fetch-modesin Claude Code to confirm it loaded.
Bundled filesreference.md
Details
From the project READMEDoctrine Fetch Modes (Symfony)
Use when
- A list or detail endpoint runs one query per row (N+1) on a relation.
- A read-only list needs a few columns, not full managed entities.
- Choosing
LAZY,EAGERorEXTRA_LAZYon a mapping, or porting ORM 2 code that relied onPARTIALobjects. - A report or projection query drops to raw SQL through DBAL 4.
Default workflow
- Confirm the N+1 or over-fetch in the Symfony profiler before changing any mapping.
- Keep relations on
fetch: 'LAZY'; setfetch: 'EXTRA_LAZY'on large collections socount(),contains()andslice()run targeted SQL. - Load the relations a use case needs with a fetch join in the repository (
addSelect()plusleftJoin()). - For read-only lists, project into a
readonlyDTO withSELECT NEW(constructor argument order must match theNEWlist). - Use
Query::HINT_READ_ONLYor an index-by alias (createQueryBuilder('p', 'p.id')) when the result is only displayed or looked up by id. - For raw SQL, use the DBAL 4 methods (
fetchAllAssociative(),fetchOne(),executeStatement()).
Guardrails
PARTIALin DQL fails on ORM 3.0 to 3.2 and only returns from 3.3: useSELECT NEWDTOs for read-only lists instead.- Avoid
fetch: 'EAGER'on a mapping; a fetch join in the query gives the same result per use case. SELECT NEWreturns DTOs, not managed entities: never modify or flush them.- DBAL 4 removed
query(),exec()andfetchAll().
Progressive disclosure
- Use this file for execution posture and risk controls.
- Open references when deep implementation details are needed.
Output contract
- Repository methods with the fetch strategy chosen per use case.
- DTO classes and the
SELECT NEWqueries that fill them. - Query count before and after, from the profiler or
doctrine:query:dql --show-sql.
References
reference.md
Comments
Markdown supported