将鉴别器列映射到具有Doctrine 2的字段

时间:2014-01-22 13:58:57

标签: doctrine-orm

在我的项目中,我有几个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; }

    // ...
}

有没有办法让这项工作符合学说?或者我需要在实体到数组方法中读取类元数据吗?

4 个答案:

答案 0 :(得分:17)

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

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

class Person
{
    protected $discr = 'person';

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

答案 1 :(得分:3)

以下是我在一个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,它将是相同的,除了您将拥有实体经理的文档管理器。

答案 2 :(得分:2)

刚刚解决了这个问题而没有将鉴别器定义为真正的成员:

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 {}

答案 3 :(得分:1)

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

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