【发布时间】:2014-10-03 07:51:15
【问题描述】:
在更新带有关联/链接的分离实体时,我们遇到了一些困难。我们有一个文章实体,它与类别实体具有多对多关系。
当通过表单向现有文章添加类别并提交时,我们会收到以下消息:
执行“INSERT INTO 文章...重复条目“测试”时发生异常
这很奇怪,因为实体是现有的(带有 id),为什么要使用插入?
由于文章实体被分离/序列化,我们尝试合并它,这次我们没有收到错误,但没有新的类别链接插入到数据库中。我们统计了合并之前和之后的类别,发现它们在合并时被重置为数据库状态,所以如果它最初有 2 个类别,我们添加了第三个类别,则合并前的计数为 3,合并后为 2。新的类别也是一个部分实体,只包含类别的 id。
代码如下:
$connection->beginTransaction();
try {
// Manage model by doctrine if it's not.
$modelState = $entityManager->getUnitOfWork()->getEntityState($model);
if ($modelState !== UnitOfWork::STATE_MANAGED) {
$model = $entityManager->merge($model); // Strips new categories.
}
$entityManager->persist($model);
$entityManager->flush();
$connection->commit();
} catch (\Exception $e) {
$connection->rollback();
}
实体:
<entity name="Article" table="articles" repository-class="Doctrine\Repository\BaseRepository">
<id name="id" type="integer" column="id">
<generator strategy="IDENTITY"/>
</id>
<field name="title" type="string" column="title" length="50" nullable="true"/>
<many-to-many field="categories" target-entity="ArticleCategory" inversed-by="articles">
<cascade>
<cascade-persist/>
</cascade>
<join-table name="article_category_links">
<join-columns>
<join-column name="article_id" referenced-column-name="id" on-delete="CASCADE"/>
</join-columns>
<inverse-join-columns>
<join-column name="article_category_id" referenced-column-name="id" on-delete="CASCADE"/>
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
<entity name="ArticleCategory" table="article_categories" repository-class="Doctrine\Repository\BaseRepository">
<id name="id" type="integer" column="id">
<generator strategy="IDENTITY"/>
</id>
<field name="name" type="string" column="name" length="200" nullable="true"/>
<many-to-many field="articles" target-entity="Article" mapped-by="categories">
<cascade>
<cascade-persist/>
</cascade>
</many-to-many>
</entity>
更新
这就是我们正在做的:
1.表格$_POST数据,第三类是新的:
Array
(
[id] => 1
[title] => test
[categories] => Array
(
[0] => Array
(
[id] => 1
)
[1] => Array
(
[id] => 2
)
[2] => Array
(
[id] => 3
)
)
)
2。反序列化的文章(JMS\Serializer):
Article Object
(
[id:protected] => 1
[title:protected] => test
[categories:protected] => Array
(
[0] => ArticleCategory Object
(
[id:protected] => 1
[name:protected] =>
[articles:protected] =>
)
[1] => ArticleCategory Object
(
[id:protected] => 2
[name:protected] =>
[articles:protected] =>
)
[2] => ArticleCategory Object
(
[id:protected] => 3
[name:protected] =>
[articles:protected] =>
)
)
)
3。合并分离/反序列化的文章,删除第三类..
$article = $entityManager->merge($article);
4.刷新,更新所有文章数据,但没有链接到第三个类别,因为它被删除了。
$entityManager->flush();
以下是更多示例/测试:
// With attached article and no merging.
// Creates the link to the article, but the category becomes a new one (new id)..
$article = $articleRepository->getById(1)->getItem();
$category = new ArticleCategory();
$category->setId(3); // This doesnt matter since it becomes a new one.
$article->addCategory($category);
$articleRepository->getEntityManager->flush();
// With attached article and merging of category.
// Creates the link to the article but it clears all the category fields..
$article = $articleRepository->getById(1)->getItem();
$category = new ArticleCategory();
$category->setId(3);
$category = $categoryRepository->getEntityManager->merge($category);
$article->addCategory($category);
$articleRepository->getEntityManager->flush();
// With detached and merged article.
// No links no errors, but other article fields gets updated.
$category = new ArticleCategory();
$category->setId(3);
$article->addCategory($category);
echo count($article->getCategories()); // 3
$article = $articleRepository->getEntityManager->merge($article);
echo count($article->getCategories()); // 2, the new one gets removed.
$articleRepository->getEntityManager->flush();
【问题讨论】:
标签: php doctrine-orm