Symfony2 / Doctrine2 - ManyToOne - 保存反面

时间:2014-09-27 02:27:40

标签: symfony doctrine-orm entity one-to-many many-to-one

我是Symfony和Doctrine的新手。

我有一个实体“用户”和一个实体“类型”。一个用户可以拥有一个喜欢的类型,一个类型可以拥有许多具有该特定类型作为收藏的用户。所以我需要一个多(用户)到一个(类型)的关系。

我实现了它,它工作正常(大多数情况下)。但有一件事我不明白。

如果我这样做,那就有效:

$user = new User();
$type = new Type();

$user->setFavoriteType($type);
$em->persist($user);
$em->persist($type);
$em->flush();

生成对象并将其存储到DB。并且正确设置了favorite_type_id。 所以改变拥有方可以按预期工作

但是如果我将用户添加到反面(仅)并刷新实体管理器,则不设置favorite_type_id。

$user = new User();
$type = new Type();

$type->getUsers()->add($user); //same with $type->addUser($user);
$em->persist($user);
$em->persist($type);
$em->flush();

为什么?有没有理由说它不能从反面起作用?我真的必须手动设置吗?如果我操作类型实体中的addUser方法,如“$ user-> setFavoriteType($ this)”,它可以工作。但这不应该是学说的任务吗?

文档说

  

更新双向关联时,Doctrine仅检查双方中的一方以获取这些更改。这被称为协会的拥有方。

所以这似乎是通缉行为,是吗?但为什么?由于表现?语义原因?

如果有人能向我解释或告诉我我做错了什么,我会很高兴。

2 个答案:

答案 0 :(得分:3)

查看Doctrine documentation on cascading.。这可以通过添加cascade={"persist"}并清除缓存(以重建Doctrine的元数据缓存)来帮助您快速轻松地开始您想要做的事情。

答案 1 :(得分:0)

这是因为从根本上说,在考虑持久性时,Doctrine将PHP实体直接映射到数据库表。在您的情况下,用户和类型在概念上具有多对一关系,但在数据库级别,关系完全在用户表上表示 - 用户具有收藏类型,因此用户表具有{{1} }列。虽然我们可以想到Type Entities有一个他们最喜欢的用户列表,但这实际上也是通过查看User表得出的,Type表中没有任何内容。

在Doctrine中设置实体映射告诉Doctrine实体之间的关系是什么,并允许Doctrine为您提供某些方便的访问方法,如favorite_type_id,但不会更改基础数据的存储方式。如果我使用$type->getUsers()我正在操纵有直接数据库对应的数据,但是,默认情况下,如果我调用$user->setFavoriteType我不是 - 这样做的主要目的是进行这种调用-the-box用于保持您当前正在使用的水合实体是最新的,而不是简单地扔掉物品并再次从数据库中取出它们。

当然,您已经看到自定义$type->addUser也可以调用addUser,或者像Shon M建议的那样配置级联持久性,以使行为更像您期望的那样/想要它。从一开始就把它排除在外似乎是浪费时间,但我怀疑Doctrine开发人员有意识地选择以最简单的方式实现所需的功能,而documenting it clearly并提供了几个简单的替代方案,如果这样&# 39;你所追求的是什么,从而以某种方式迎合每个人。无论喜欢与否,数据库中的数据以及PHP后期水合中运行的数据在技术上都是不同的东西,特别是像Doctrine这样的模型,其中DB活动被推迟到开发人员请求它,并且它很有意义使所有这一切尽可能明确!