Что такое ORM и как он используется в PHP?

«Что такое ORM и как он используется в PHP?» — вопрос из категории Базы данных, который задают на 35% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

ORM (Object-Relational Mapping) — это технология, которая создаёт "мост" между реляционной базой данных и объектно-ориентированной моделью приложения. Вместо написания сырых SQL-запросов разработчик работает с объектами и их свойствами, а ORM автоматически транслирует эти операции в SQL-команды.

Как это работает в PHP (на примере Doctrine):

  1. Вы описываете сущность (Entity) как обычный PHP-класс с аннотациями, атрибутами или в YAML/XML.
  2. ORM создаёт соответствующую таблицу в БД (или отображает класс на существующую таблицу).
  3. В коде вы манипулируете объектами этой сущности, а ORM отслеживает изменения и сохраняет их.

Пример сущности и работы с ней в Doctrine:

// src/Entity/Product.php
use DoctrineORMMapping as ORM;

#[ORMEntity]
#[ORMTable(name: 'products')]
class Product
{
    #[ORMId]
    #[ORMGeneratedValue]
    #[ORMColumn(type: 'integer')]
    private ?int $id = null;

    #[ORMColumn(type: 'string', length: 255)]
    private string $name;

    #[ORMColumn(type: 'decimal', precision: 10, scale: 2)]
    private float $price;

    // Геттеры и сеттеры...
    public function getId(): ?int { return $this->id; }
    public function getName(): string { return $this->name; }
    public function setName(string $name): void { $this->name = $name; }
    public function getPrice(): float { return $this->price; }
    public function setPrice(float $price): void { $this->price = $price; }
}

// Работа с данными через EntityManager
$product = new Product();
$product->setName('Laptop');
$product->setPrice(999.99);

// Сохраняем (INSERT)
$entityManager->persist($product);
$entityManager->flush(); // Выполняется SQL: INSERT INTO products ...

// Запрос (SELECT) через DQL (Doctrine Query Language) или Repository
$repository = $entityManager->getRepository(Product::class);
$expensiveProducts = $repository->findBy(['price' => 500], ['name' => 'ASC']);

// Или через QueryBuilder
$queryBuilder = $repository->createQueryBuilder('p');
$query = $queryBuilder->where('p.price > :price')
                      ->setParameter('price', 500)
                      ->orderBy('p.name', 'ASC')
                      ->getQuery();
$result = $query->getResult();

Преимущества ORM в PHP:

  • Повышение продуктивности: Автоматизация CRUD-операций.
  • Безопасность: Защита от SQL-инъекций через параметризованные запросы.
  • Переносимость: Абстракция от конкретной СУБД (MySQL, PostgreSQL, SQLite).
  • Удобство объектной модели: Работа с данными в привычной парадигме ООП.

Недостатки и подводные камни:

  • Проблема N+1: Неоптимальные запросы при ленивой загрузке связанных коллекций. Решается жадной загрузкой (fetch: 'EAGER', JOIN в DQL).
  • Сложность оптимизации: Для очень сложных аналитических запросов сырой SQL может быть эффективнее.
  • Оверхеад: Для простых операций ORM добавляет дополнительную прослойку.

Популярные PHP ORM: Doctrine (наиболее мощный и распространённый в enterprise), Eloquent (встроен в Laravel, более простой и удобный), Propel. Выбор зависит от сложности проекта и фреймворка.

Видео-ответы