Перейти к основному содержимому

Doctrine ORM и слой работы с базой данных в Symfony

Doctrine — это набор PHP-библиотек, ориентированных на хранение данных и объектно-реляционное отображение (ORM).

1. Паттерн Data Mapper​

В отличие от Eloquent в Laravel (Active Record), Doctrine использует паттерн Data Mapper. Это означает, что ваши сущности (PHP-классы) — это обычные объекты (POPO), которые ничего не знают о том, как они сохраняются в базе данных. Логику персистентности берёт на себя EntityManager.

2. Основные компоненты​

  • EntityManager: Главный интерфейс для работы с Doctrine. Используется для сохранения, синхронизации, поиска и удаления сущностей.
  • Unit of Work: Внутренний компонент, отслеживающий все объекты, которые в данный момент «управляются» EntityManager. При вызове flush() он вычисляет различия и выполняет необходимые SQL-запросы.
  • Repositories: Классы, содержащие пользовательскую логику получения сущностей (например, findByEmail).

3. Жизненный цикл сущности и события​

Doctrine позволяет встраиваться в различные этапы жизненного цикла сущности:

  • prePersist, postPersist
  • preUpdate, postUpdate
  • preRemove, postRemove
  • postLoad

Обработка возможна с помощью Lifecycle Callbacks (внутри сущности) или Event Listeners/Subscribers (отдельные классы).

4. DQL vs DBAL​

  • DQL (Doctrine Query Language): Объектно-ориентированный язык запросов, похожий на SQL, но работающий с PHP-классами и свойствами вместо имён таблиц и столбцов.
  • DBAL (Database Abstraction Layer): Низкоуровневая библиотека, предоставляющая единый API для взаимодействия с различными СУБД (MySQL, PostgreSQL и др.) через «сырой» SQL.

5. Стратегии загрузки​

  • Lazy Loading: Связанные сущности загружаются из базы данных только при непосредственном обращении к ним (по умолчанию для коллекций).
  • Eager Loading: Связанные сущности загружаются сразу в том же запросе (с использованием JOIN).

6. Частые вопросы на собеседованиях​

  • flush() vs persist(): persist() указывает Doctrine «управлять» объектом; flush() фактически выполняет SQL-команды для сохранения изменений в базе данных.
  • Наследование при маппинге: Doctrine поддерживает несколько способов отображения наследования классов на таблицы базы данных:
    • Mapped Superclass: Таблицы создаются только для дочерних классов.
    • Single Table Inheritance: Все классы иерархии хранятся в одной таблице с колонкой-дискриминатором.
    • Class Table Inheritance: У каждого класса своя таблица, связанная внешними ключами.