我正在解析一个包含很多项目的大型XML文件。每个项目都有很多类别,可以重复。这是一个XML示例。
<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>
使用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);
}
}
}
}
事情是:当我完成所有项目的循环时,我只有flush()
实体管理员。因此,$query->getQuery()->getOneOrNullResult()
始终会返回null
,从而导致我创建重复的类别。
在上面的XML示例中,我有以下内容:
| 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 |
我想要以下内容:
| 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->flush()
解决它之后简单地添加$em->persist($categoryEntity)
,但我不想再刷新内容(或者就此而言,只刷新一个类别)。有很多未完成的事情要做,我不想打断我的交易。我希望仍然能够回滚到最开始并排除所有未使用的类别,如果我需要(显然,不运行其他查询)。
我的问题是:有没有办法访问数据库和doctrine的内部实体映射,以检索可能有也可能没有ID的实体?或者我是否必须自己创建此映射,运行DQL并检查我的映射?
答案 0 :(得分: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;
}
}
将新类别实体存储在$_created_categories
数组中没有内存开销,因为所有对象都是通过PHP中的引用进行操作的。