我们正在将应用程序移植到Symfony2,目前正在使用doctrine ORM。我们在数据库中有一堆坏的外键,并且越来越难以进行关系映射而不会遇到“未找到实体”#34;例外。它是清理数据库的路线图,但不幸的是,我们现在无法解决这个问题。有没有什么方法可以让它只是返回null如果它找不到合适的实体?
如果我有以下关系映射:
User:
type: entity
table: user
id:
userID:
type: integer
generator:
strategy: NONE
fields:
contactName:
type: string
length: 255
nullable: false
contactPhone:
type: string
length: 255
nullable: false
companyName:
type: string
length: 255
nullable: false
username:
type: string
length: 255
nullable: false
password:
type: string
length: 255
nullable: false
email:
type: string
length: 255
nullable: false
manyToOne:
address:
targetEntity: Address
joinColumn:
name: addressID
referencedColumnName: addressID
nullable: true
default: null
-----------------------------------------------------
Address:
type: entity
table: address
id:
addressID:
type: integer
generator:
strategy: AUTO
fields:
street:
type: string
length: 255
nullable: false
street2:
type: string
length: 255
nullable: false
city:
type: string
length: 255
nullable: false
state:
type: string
length: 32
nullable: false
zip:
type: string
length: 10
nullable: false
country:
type: string
length: 40
nullable: false
似乎如果用户表中的addressID存在错误值,我将得到"未找到实体。"通过串行器发送时的异常。
答案 0 :(得分:0)
是的,这完全有可能,但我很难告诉你如何做到这一点,因为你没有提供任何例子。你能给出一些现有的代码示例,我可以给你一个建议吗?
您是否在存储库中进行查询:
$qb = $this->entityManager->createQueryBuilder();
$qb->select('e')
->from('MyBundle:Entity', 'e')
->where($qb->expr()->eq('e.id', ':id'))
->setParameter('id', 1)
->setMaxResults(1);
$result = $qb->getQuery()->getOneOrNullResult();
如果找不到实体,结果将包含null。但我认为大多数find *方法都会返回null。从Doctrine2检查Repository类。如果需要,您还可以扩展Doctrine的存储库并覆盖方法,以防出现异常。你可以捕获它并返回null,空数组或任何手工制作的对象......等等。
如果您正在进行任何连接,如果您不确定数据是否存在,请考虑使用左连接。在访问代码中的引用对象时,例如,如果您有:
$user->getProfile();
并且存在可能返回null的危险,在返回对象之前检查方法本身,如下所示:
public function getProfile()
{
if ($this->profile === null) {
return new DummyProfile();
}
return $this->profile;
}
DummyProfile可以扩展原始的Profile对象,它可以像一个模拟对象,返回一些默认值。您还可以将此虚拟对象保存在属性中,并在下次返回它,因此不会一直实例化(单例模式)。这是你可以保护你的代码的方法,因此你不会在null上调用方法,这会导致php错误。
希望能让你知道如何继续... :)
答案 1 :(得分:0)
啊,这是我们经常看到的PITA。如果你已经禁用延迟加载,那么Doctrine可以加载&为当时所有相关实体提供保湿。但是,当你尝试在Symfony中渲染模板/表单时,我猜它已经开启并且它正在死亡。
启用Lazy Loading时,加载实体时不会出现错误,但是如果您尝试访问相关实体的属性(这将导致Doctrine加载它)或渲染,您将收到错误symfony表单中的实体和表单上的字段与外表的属性相关。
不幸的是,没有简单的方法来阻止或抓住这个。我的建议是手动检查数据是否存在错误的外键并清理数据,Doctrine的延迟加载对于坏数据尤其不可原谅,而Symfony只是通过在遇到duff链接时使用Error 500来加剧这种情况。 / p>
答案 2 :(得分:0)
我刚遇到同样的问题,在寻找解决方案时发现了这个问题……我没有找到。这是我所做的(使用注释):
使关系变得懒惰:
"//*[contains(@id,'itsAnExampleBoi')]/div[1]/div[2]"
修改吸气剂并始终使用它-即使在类内部也是如此:
/**
* @var Resource
*
* @ORM\JoinColumn(name="ResourceID", referencedColumnName="ResourceID")
* @ORM\OneToOne(targetEntity="Resource", fetch="LAZY")
*/
private $resource;
private $_resource_is_valid = null;
这种方法允许Doctrine对实体进行部分水合,并使您可以在控制力更强的区域捕获不良关系。