【问题标题】:Map a discriminator column to a field with Doctrine 2使用 Doctrine 2 将鉴别器列映射到字段
【发布时间】:2014-02-12 15:08:44
【问题描述】:

在我的项目中,我有几个这样的class table inheritances

namespace MyProject\Model;

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
 */
class Person
{
    // ...
}

/** @Entity */
class Employee extends Person
{
    // ...
}

我有一种方法可以根据具有公共 getter 的字段将实体转换为数组。这里的问题是我丢失了数组中的继承信息,因为鉴别器值没有存储在字段中。

所以我尝试了以下,希望学说会自动设置$disc

class Person
{
    // can I automatically populate this field with 'person' or 'employee'?
    protected $discr;

    public function getDiscr() { return $this->discr; }
    public function setDiscr($disc) { $this->discr; }

    // ...
}

有没有办法让这在教义中发挥作用?或者我需要在我的实体到数组方法中读取类元数据吗?

【问题讨论】:

标签: doctrine-orm


【解决方案1】:

遗憾的是,没有记录方法可以将 discr 列映射到实体。那是因为 discr 列实际上是数据库的一部分,而不是实体。

但是,将 discr 值直接放在类定义中是很常见的。它不会改变,无论如何你总是会以相同的值获得相同的类。

class Person
{
    protected $discr = 'person';

class Employee extends Person
{
    protected $discr = 'employee';

【讨论】:

  • 当您需要在 WHERE 子句中访问您的鉴别器时,这无济于事。 INSTANCE OF 有点像,但这种数据屏蔽对我来说真的很奇怪(而且丑陋)。只会带来复杂性和局限性,imo。
  • 您可能没有抓住重点。鉴别器只能通过 Doctrine 访问。您无法在 DQL 语句中访问它。的实例是 DQL 方法。是的,有很多限制。但是 SQL 本身不允许在单个列和多个表之间建立关系。如果有,那就太好了。
  • 我很遗憾地注意到了这一点。我不明白的是为什么 Doctrine 不允许一个人获得价值,这是非常有用的(无论是“哪里”,还是任何需要它的计算。)我只是不得不在最近使用这个功能dev,但是知道它对性能的影响,在限制之前进行所有连接(WHERE 子句),并在他们的示例中将 strings 作为鉴别键真的让我感到困惑. 我的评论的重点是讲述INSTANCE OF.,因为 Doctrine 使这变得非常复杂。这里没有答案。
  • 你有没有注意到日期?我不肯定 Doctrine 早在 2014 年就有 operator 的实例。问题当然是关于访问鉴别器列。不是查询。但无论你如何实现,试图将继承映射到 sql 数据库是很尴尬的。
  • 我没有注意日期,只是想补充一点,因为这个问题在搜索结果中的排名可能还不错。无论如何,完全同意你的看法,并不想用 cmets 来打扰你。只是想添加一些我认为有用的信息,但我在这里没有找到。
【解决方案2】:

这是我在一个 ZF2 项目中的一个小例子(使用 Doctrine MongoDB ODM):

// an instance of your entity
$entity = ...;

/** @var \Doctrine\ODM\MongoDB\DocumentManager $documentManager */
$documentManager = $serviceManager->get('DocumentManager');

/** @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory $factory */
$factory = $documentManager->getMetadataFactory()

/** @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadata $metadata */
$metadata = $factory->getMetadataFor(get_class($object));

if ($metadata->hasDiscriminator()) {
     // assuming $data is result of the previous extraction
     $data[$metadata->discriminatorField] = $metadata->discriminatorValue;
}

我所做的是我实现了一个自定义接口DiscriminatorAwareInterface,并且我只将检查应用于实现它的类(在你的情况下,它将是所有“可区分”类扩展的类。

因此,我最终得到如下代码:

// add value of the discrinimator field to entities that support it
if ($object instanceof DiscriminatorAwareInterface) {
    /** @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadata $metadata */
    $metadata = $factory->getMetadataFor(get_class($object));

    if ($metadata->hasDiscriminator()) {
        $data[$metadata->discriminatorField] = $metadata->discriminatorValue;
    }
}

我敢肯定,如果你使用标准 ORM,它会是一样的,除了你将拥有实体管理器而不是文档管理器。

【讨论】:

    【解决方案3】:

    刚刚遇到这个问题,并没有将鉴别器定义为真正的成员就解决了:

    abstract class MyEntity {
        const TYPE_FOO = 'foo';
        const TYPE_BAR = 'bar';
        const TYPE_BUZ = 'buz';
        ...
        /**
         * @return string
         */
        public function getMyDiscriminator()
        {
            $myDiscriminator = null;
            switch (get_class($this)) {
                case MyEntityFoo::class:
                    $myDiscriminator = self::TYPE_FOO;
                    break;
                case MyEntityBar::class:
                    $myDiscriminator = self::TYPE_BAR;
                    break;
                case MyEntityBuz::class:
                    $myDiscriminator = self::TYPE_BUZ;
                    break;
            }
            return $myDiscriminator;
        }
        ...
    }
    
    class MyEntityFoo extends MyEntity {}
    
    class MyEntityBar extends MyEntity {}
    
    class MyEntityBuz extends MyEntity {}
    

    【讨论】:

    • 你是如何让 Doctrine 从 getMyDiscriminator() 读取 DiscriminatorMap 的?
    【解决方案4】:

    您可以使用以下解决方案:

    `$`$metadata = \Doctrine\ORM\Mapping\ClassMetadata((string)$entityName);
    print_r($metadata->discriminatorValue);`
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多