2013-04-11 2 views
0

많은 항목이있는 큰 XML 파일을 구문 분석하고 있습니다. 각 항목에는 여러 범주가 있으며 반복 할 수 있습니다. 다음은 샘플 XML입니다.Doctrine : 아직 데이터베이스에 저장되지 않은 엔티티 검색

$em = $this->getDoctrine()->getEntityManager(); 

foreach ($items as $item) { 

    [...] 

    $categories = ... //Array with category names, parsed from the XML. 

    foreach ($categories as $category) { 

     //This will check if the 'item' entity 
     //already has a category with that name. 
     $exists = $entity->getCategories()->exists(function($key, $element) use ($category) { 
      return $category == $element->getName(); 
     }); 

     if (!$exists) { 

      //If there's already one on the database, we'll load it. 
      //Otherwise, we'll save a new Category.. 
      $query = $this->_entityManager->createQueryBuilder(); 
      $query->select('c') 
        ->from("MyBundle:Category, 'c'); 
        ->where("c.name = :name") 
        ->setParameter("name", $category); 

      } 

      $result = $query->getQuery()->getOneOrNullResult(); 

      if ($result != null) { 
       $item->addCategory($result); 
      } else { 
       $categoryEntity = new Category($category); 
       $em->persist($categoryEntity); 
       $item->addCategory($categoryEntity); 
      } 

     } 

    } 

} 

건은 다음과 같습니다 : 다 대다 관계는 위에서 설명한 처리 교리를 사용

<item> 
    <category>Category1</category> 
    <category>Category2</category> 
    <category>Category3</category> 
    <category>Category4</category> 
    <category>Category5</category> 
</item> 
<item> 
    <category>Category1</category> 
    <category>Category2</category> 
    <category>Category3</category> 
    <category>Category7</category> 
    <category>Category9</category> 
</item> 

는,이 같은 샘플 코드가 난 단지 flush() EntityManager를 나는 통해 반복 완료시 모든 아이템. 따라서 $query->getQuery()->getOneOrNullResult()항상null을 반환하므로 중복 된 범주를 만들 수 있습니다.

| item | 
| 1 | 
| 2 | 

| category.id, category.name | 
| 1,   Category1  | 
| 2,   Category2  | 
| 3,   Category3  | 
| 4,   Category4  | 
| 5,   Category5  | 
| 6,   Category1  | 
| 7,   Category2  | 
| 8,   Category3  | 
| 9,   Category7  | 
| 10,   Category9  | 

| item | category | 
| 1 | 1  | 
| 1 | 2  | 
| 1 | 3  | 
| 1 | 4  | 
| 1 | 5  | 
| 2 | 6  | 
| 2 | 7  | 
| 2 | 8  | 
| 2 | 9  | 
| 2 | 10  | 

내가 다음 원 : 위의 XML 예제에서

, 나는 다음과 같은 한

| item | 
| 1 | 
| 2 | 

| category.id, category.name | 
| 1,   Category1  | 
| 2,   Category2  | 
| 3,   Category3  | 
| 4,   Category4  | 
| 5,   Category5  | 
| 6,   Category7  | 
| 7,   Category9  | 

| item | category | 
| 1 | 1  | 
| 1 | 2  | 
| 1 | 3  | 
| 1 | 4  | 
| 1 | 5  | 
| 2 | 1  | 
| 2 | 2  | 
| 2 | 3  | 
| 2 | 9  | 
| 2 | 10  | 

간단히 $em->persist($categoryEntity) 그것을 해결 $em->flush() 후 추가,하지만 난 플러시하고 싶지 않아 그냥 아직 (또는 카테고리에 대한 플러시). 미완성 물건이 많이 있고 내 거래를 방해하고 싶지 않습니다. 나는 여전히 초반부로 롤백 할 수 있고 필요하다면 사용되지 않는 카테고리를 모두 제외 할 수 있기를 원합니다. (물론 추가 쿼리를 실행하지 않아도됩니다.)

내 질문은 : 데이터베이스 및 doctrine의 내부 엔터티 매핑에 액세스하여 ID가 ​​있거나없는 엔터티를 검색 할 수있는 방법이 있습니까? 또는이 매핑을 직접 만들고 DQL을 실행하고 매핑을 확인해야합니까?

답변

1

Doctrine2는 이것을 수행 할 수 없지만 루프에서 새로 생성 된 카테고리를 저장하고 데이터베이스에서 MISS를 가져올 때 확인하십시오.

$_created_categories = array(); 

    if (!$exists) { 
     // If there's already one on the database, we'll load it. 
     // Otherwise, we'll save a new Category.. 

     $query = $this->_entityManager->createQueryBuilder(); 
     $query->select('c') 
       ->from("MyBundle:Category, 'c'); 
       ->where("c.name = :name") 
       ->setParameter("name", $category); 

     $result = $query->getQuery()->getOneOrNullResult(); 

     if ($result) { 
      $item->addCategory($result); 
     elseif (isset($_created_categories[$category])) { 
      $item->addCategory($_created_categories[$category]); 
     } else { 
      $categoryEntity = new Category($category); 
      $em->persist($categoryEntity); 
      $item->addCategory($categoryEntity); 

      $_created_categories[$category] = $categoryEntity; 
     } 
    } 

모든 개체 PHP 참고로 manipuled되는 것과 $_created_categories 어레이의 새로운 카테고리 엔티티를 저장하기위한 메모리 어떠한 오버 헤드도 없다.

+0

나는 교리로 그것을 성취 할 수 없을까 두려웠다. 문제는 : 나의 수업은 내가 위에 올린 수업과 다소 다르다. 그것은 항목 및 카테고리에서만 작동하도록되어 있지 않으므로보다 일반적입니다. 간단한 배열보다 더 강력한 로컬 매핑이 필요할 수 있습니다. 지금부터 시작하겠습니다. 그래도 고맙습니다. –

관련 문제