简体   繁体   English

如何在Doctrine中将外键既作为字段又作为映射映射到实体上?

[英]How to map a foreign key on an entity both as field and mapping in Doctrine?

Background (short version): Symfony4 application in which I use a custom data layer over doctrine entity layer so the business logic layer is not dependent on the database schema. 背景(简短版本):Symfony4应用程序,其中我在原则实体层上使用了自定义数据层,因此业务逻辑层不依赖于数据库架构。 This is not changeable for the moment. 目前这是无法更改的。

In some cases it's easier to use have the foreign key mapped as a field: 在某些情况下,将外键映射为字段更容易使用:

/**
 * @var string
 *
 * @ORM\Column(name="article_id", type="string")
 */
protected $articleId;

but in other cases for the same entity I need the relation: 但是在其他情况下,对于同一实体,我需要建立以下关系:

/**
 * @var Article
 *
 * @ORM\OneToOne(targetEntity="Article")
 * @ORM\JoinColumn(name="article_id", referencedColumnName="id")
 */
protected $article;

to not have the same entity in 2 copies, I added the snippets above in one single class. 为了在2个副本中没有相同的实体,我在一个类中添加了以上代码段。 If I hydrate the relation, everything works well ( $articleId is ignored ) but if only the $articleId is provided and $articles is null, doctrine will insert in DB null for the foreign key. 如果我对该关系进行了混合处理,则一切正常(忽略$ articleId),但是如果仅提供$ articleId且$ articles为null,则该理论将为外键在DB中插入null。

I found a possible solution: I parse the class metadata, and if in $class->associationMappings['joinColumnFieldNames'] exists fields that I also have as fields in the object, I remove the association mapping: 我找到了一种可能的解决方案:我解析类元数据,并且如果在$class->associationMappings['joinColumnFieldNames']存在我也作为对象中的字段存在的字段,则删除关联映射:

doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php 学说/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]);
        }
    }

    /* .... */

}

Is it ethically to do such thing? 做这样的事情在伦理上吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM