Ответ
В разработке на PHP, особенно с фреймворками вроде Symfony/Laravel, выборка данных из БД осуществляется на разных уровнях абстракции. Вот основные подходы:
1. Нативный SQL (с использованием PDO): Прямое выполнение SQL-запросов. Дает максимальный контроль и производительность для сложных запросов.
$stmt = $pdo->prepare("SELECT id, name, email FROM users WHERE active = :active AND created_at > :date");
$stmt->execute(['active' => 1, 'date' => '2024-01-01']);
$users = $stmt->fetchAll(PDO::FETCH_ASSOC); // или fetch() для одной строки
2. Query Builder (Построитель запросов): Объектно-ориентированный API для построения SQL-запросов. Безопаснее и гибче, чем конкатенация строк.
// Пример с Doctrine DBAL (Symfony)
$queryBuilder = $connection->createQueryBuilder();
$users = $queryBuilder
->select('u.id', 'u.name', 'u.email')
->from('users', 'u')
->where('u.active = :active')
->andWhere('u.created_at > :date')
->setParameter('active', 1)
->setParameter('date', '2024-01-01')
->executeQuery()
->fetchAllAssociative();
3. ORM (Object-Relational Mapping, например, Doctrine ORM): Работа с данными как с объектами. Самый высокоуровневый подход.
- Методы репозитория:
$userRepository = $entityManager->getRepository(User::class); $user = $userRepository->find(123); // По первичному ключу $activeUsers = $userRepository->findBy(['active' => true]); // По простым критериям - DQL (Doctrine Query Language) или QueryBuilder Doctrine ORM: Для сложных запросов с объединениями.
$query = $entityManager->createQuery( 'SELECT u, p FROM AppEntityUser u JOIN u.posts p WHERE u.active = :active ORDER BY u.name' )->setParameter('active', 1); $users = $query->getResult(); // Возвращает массив объектов User с заполненной коллекцией posts
4. «Жадная» (EAGER) vs «Ленивая» (LAZY) загрузка:
- Ленивая (по умолчанию в Doctrine): Связанные сущности (например, посты пользователя) загружаются только при первом обращении к ним. Может привести к проблеме N+1 запроса.
- Жадная: Связанные сущности загружаются сразу в основном запросе (через
JOIN). Задается в аннотации@ORMManyToOne(fetch="EAGER")или в DQL/QueryBuilder явнымJOINи выборкой.
Критерии выбора:
- ORM (Doctrine) — для основной бизнес-логики, где удобна работа с объектами.
- Query Builder (DBAL) — для сложных отчетов или административных страниц, где ORM может быть неэффективен.
- Нативный SQL — для крайне специфичных или оптимизированных запросов, которые сложно выразить через ORM/Query Builder.