Doctrine Repositories & DQL
Custom repository classes hold your queries. DQL is Doctrine's SQL-like language that operates on entities, not tables.
- Generate with `make:entity` or extend `ServiceEntityRepository` manually.
- `QueryBuilder` is the fluent way to build queries — composable and refactor-friendly.
- Use `addSelect('r')` + `join(...)` to fetch related entities in one query (eager fetch joins) — fixes N+1.
- For lists, project to DTOs with `SELECT NEW App\Dto\UserListItem(...)` to avoid hydrating full entities.
- Drop to native SQL via `Connection::executeQuery()` when the query is complex or DBMS-specific (e.g. MySQL FULLTEXT).
public function findActiveWithProfile(): array
{
return $this->createQueryBuilder('u')
->addSelect('p')
->leftJoin('u.profile', 'p')
->where('u.active = :active')
->setParameter('active', true)
->getQuery()
->getResult();
}
Common gotchas
- N+1: hydrating a list of entities then accessing a relation in a loop fires one extra query per row. Always join when you know you will need the relation.
- DQL operates on entities and properties, NOT tables and columns. `FROM App\Entity\User u WHERE u.email = ...`.