背景(简短版本(:Symfony4应用程序,其中我在原则实体层上使用自定义数据层,因此业务逻辑层不依赖于数据库模式。这暂时是不可改变的。
在某些情况下,将外键映射为字段会更容易使用:
/**
* @var string
*
* @ORMColumn(name="article_id", type="string")
*/
protected $articleId;
但在其他情况下,对于同一实体,我需要关系:
/**
* @var Article
*
* @ORMOneToOne(targetEntity="Article")
* @ORMJoinColumn(name="article_id", referencedColumnName="id")
*/
protected $article;
为了在 2 个副本中没有相同的实体,我将上面的代码片段添加到一个类中。如果我对关系进行水化,一切正常($articleId被忽略(,但如果只提供$articleId并且$articles为空,则 doctrine 将在 DB 中插入外键的 null。
我找到了一个可能的解决方案:我解析类元数据,如果$class->associationMappings['joinColumnFieldNames']
中存在我在对象中也有字段的字段,我会删除关联映射:
doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php
private function doMerge($entity, array &$visited, $prevManagedCopy = null, array $assoc = [])
{
$oid = spl_object_hash($entity);
if (isset($visited[$oid])) {
$managedCopy = $visited[$oid];
if ($prevManagedCopy !== null) {
$this->updateAssociationWithMergedEntity($entity, $assoc, $prevManagedCopy, $managedCopy);
}
return $managedCopy;
}
$class = $this->em->getClassMetadata(get_class($entity));
/* Code that I added */
foreach ($class->associationMappings as $key => $mapping) {
$joinColumns = $mapping['joinColumnFieldNames'] ?? [];
if (array_intersect($joinColumns, $class->getColumnNames())) {
unset($class->associationMappings[$key]);
unset($class->reflFields[$key]);
}
}
/* .... */
}
做这样的事情合乎道德吗?