0

product任意の数のattributesdocumentsfeatures、および単一の、images、を持つことができる製品管理ツールを構築しています。関連するテーブルは他にもいくつかありますが、問題を示すにはこれで十分です。videostypebrandcategory

次のようなメソッドを含む Model クラスが呼び出さ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();
    ...
  }

各 load メソッドは、最終的にこのメソッドを実行するいくつかのボイラー プレートを実行します。

  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 がより良い仕事をするようにする方法はありますか?

4

1 に答える 1

1

以前のアプローチにはいくつかの問題がありました。

まず、エンティティを既存のエンティティからロードするのではなく、リポジトリから取得していました。

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

より良いのは:

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

$this->entityManager->getRespository...次に、小さなデータ セット (1 つのテーブルまたは 1 つまたは 2 つのリレーション) を読み込むのに問題なく機能する製品エンティティを取得していfindByましたが、単一のクエリでリレーションを読み込むリポジトリのメソッドを取得する方法がありません。解決策は、queryBuilder を使用することです。

$qb = $this->entityManger->createQueryBuilder();
$query = $this->select('product',/*related tables*/)->/*joins etc.*/
$productEntity = $query->getSingleResult();
于 2013-07-26T15:08:13.380 に答える