Reference / Symfony
/

Doctrine Repositories & DQL

Custom repository classes hold your queries. DQL is Doctrine's SQL-like language that operates on entities, not tables.

Intermediate
  • 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 = ...`.