2013-07-23 4 views
0

Я строй инструмента управления продуктом, где product может иметь произвольное число attributes, documents, features, images, videos, а также один type, brand и category. Существует несколько других связанных таблиц, но этого достаточно, чтобы продемонстрировать проблему.Как уменьшить количество запросов, которые выполняет Doctrine?

Там в класс Модель называется ProductModel, который содержит метод, как это (уменьшена для ясности):

public function loadValues() { 
    //Product entity data 
    $this->id = $this->entity->getId(); 
    $this->slug = $this->entity->getSlug(); 

    // One of each of these 
    $this->loadType(); 
    $this->loadBrand(); 
    $this->loadCategory(); 

    // Arbitrary number of each of these 
    $this->loadAttributes(); 
    $this->loadDocuments(); 
    $this->loadFeatures(); 
    $this->loadImages(); 
    $this->loadVideos(); 
    ... 
    } 

Каждый из методов нагрузки делает некоторые котла пластина, которая в конечном счете выполняет этот метод:

public function loadEntitiesByProductId($productId=0) { 

    // Get all the entities of this type that are associated with the product. 
    $entities = $this->entityManager 
     ->getRepository($this->entityName) 
     ->findByProduct($productId); 

    $instances = array(); 

    // Create a Model for each entity and load the data. 
    foreach ($entities as $entity) { 
     $id = $entity->getId(); 
     $instances[$id] = new $this->childClass(); 
     $instances[$id]->entity = $entity; 
     $instances[$id]->loadValues(); 
    } 

    return $instances; 

    } 

Это нормально для случаев, когда связанный объект представляет собой отдельную таблицу, но обычно это сопоставление. В таких случаях я получаю все объекты сопоставления в первом запросе, тогда я должен запросить связанный объект в методе loadValues() (через метод Doctrine get<Entity>()). Результатом этого процесса является огромное количество запросов (часто> 100). Мне нужно избавиться от посторонних запросов, но я бы хотел сделать это, не теряя идиомы, которые я использую в своих моделях данных.

Есть ли способ заставить entityManager выполнять лучшую работу при использовании объединений для группировки этих запросов?

+0

как о [экстра-ленивым] (http://docs.doctrine-project.org/en/2.0.x/tutorials/extra-lazy-associations.html) ассоциации? В Docs: «Ассоциации по умолчанию помечены как« Lazy », что означает, что весь объект коллекции для ассоциации заполняется при первом обращении к нему. Если вы отметите ассоциацию в качестве лишнего лени, можно вызвать следующие методы в коллекциях без запуска полной загрузки коллекции ' – manix

ответ

1

Были несколько проблем с моим предыдущим подходом:

Во-первых, я получал сущности из хранилища, а не загружать их из существующего объекта:

$entities = $this->entityManager 
    ->getRepository($this->entityName) 
    ->findByProduct($productId); 

Лучше:

$method = $this->deriveGetMethod($this->entityName); 
$entities = $productEntity->$method() 

Во-вторых, я извлекал объект продукта с помощью $this->entityManager->getRespository..., который отлично подходит для загрузки небольших наборов данных (одна таблица или один или два релята ons), но нет способа получить методы репозитория для загрузки отношений в одном запросе. Решение заключается в использовании queryBuilder.

$qb = $this->entityManger->createQueryBuilder(); 
$query = $this->select('product',/*related tables*/)->/*joins etc.*/ 
$productEntity = $query->getSingleResult(); 
Смежные вопросы