我是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仅检查双方中的一方以获取这些更改。这被称为协会的拥有方。
所以这似乎是通缉行为,是吗?但为什么?由于表现?语义原因?
如果有人能向我解释或告诉我我做错了什么,我会很高兴。
答案 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活动被推迟到开发人员请求它,并且它很有意义使所有这一切尽可能明确!