我可以从doctrine2中的php访问鉴别器字段吗?

我可以从doctrine2中的php访问鉴别器字段吗?,php,inheritance,doctrine,doctrine-orm,Php,Inheritance,Doctrine,Doctrine Orm,我有一个实体,它定义了如下继承: * @DiscriminatorColumn(name="type", type="string") * @DiscriminatorMap({"text" = "TextAttribute", "boolean" = "BooleanAttribute", "numeric" = "NumericAttribute", "date" = "DateAttribute"}) 我想知道字段“type”是否可以有getter?我知道我可以使用instanceof(

我有一个实体,它定义了如下继承:

* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"text" = "TextAttribute", "boolean" = "BooleanAttribute", "numeric" = "NumericAttribute", "date" = "DateAttribute"})

我想知道字段“type”是否可以有getter?我知道我可以使用instanceof(在大多数情况下,这就是我正在做的),但是很少有情况下,$item->getType()会让我的生活变得更轻松。

不,这是不可能的,但是你可以做一些类似的事情:get_class($object)=TYPE_CONST

扩展beberlei所说的,你可以在属性类中声明一些常量,和一个抽象的
getType()
函数。然后,在每个派生属性类中重载它

比如:

abstract class Attribute {
    const TYPE_BOOL = 0;
    const TYPE_INT  = 1;
    ...
    abstract public function getType();
}

class BooleanAttribute extends Attribute {
    public function getType() {
        return parent::TYPE_BOOL;
    }
}

如果您想像我一样避免使用常量,请使用类似的方法:

public function getType()
{
    $type = explode('\\', get_class($this));

    return end($type);
}

在PHP5.3中有一种更巧妙的方法:

abstract Parent
{
    const TYPE = 'Parent';

    public static function get_type()
    {
        $c = get_called_class();
        return $c::TYPE;
    }
}

class Child_1 extends Parent
{
    const TYPE = 'Child Type #1';
    //..whatever
}

class Child_2 extends Parent
{
    const TYPE = 'Child Type #2';
    //...whatever
}

我的方法是通过元数据理论简单地访问它的价值

$cmf = $em->getMetadataFactory();
$meta = $cmf->getMetadataFor($class);
$meta->discriminatorValue
将为您提供值,作为一种方法

public static function get_type()
{
    //...get the $em instance 
    $cmf = $em->getMetadataFactory();
    $meta = $cmf->getMetadataFor(__CLASS__);
    return $meta->discriminatorValue;
}

我将扩展基本实体的每个类的元数据缓存在一个静态变量中,其中还有许多其他有用的信息

可以使用EntityManager或DocumentManager

$documentManager->getClassMetadata(get_class($entity))->discriminatorValue;
我会这样做的

首先,您创建了一个
AttributeInterface
,以确保所有未来的新属性类型都将实现need方法:

interface AttributeInterface
{
    /**
     * Return the attribute type
     */
    public function getType();
}
然后创建实现
AttributeInterface
接口的
Attribute
抽象类

使用
@DiscrimatorMap
调用中的常量以获得某种一致性

/**
 * Attribute
 * ...
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({Attribute::TYPE_TEXT = "TextAttribute", Attribute::TYPE_BOOLEAN = "BooleanAttribute", Attribute::TYPE_NUMERIC = "NumericAttribute", Attribute::TYPE_DATE = "DateAttribute"})
 */
abstract class Attribute implements AttributeInterface
{
    const TYPE_TEXT    = 'text';
    const TYPE_BOOLEAN = 'boolean';
    const TYPE_NUMERIC = 'numeric';
    const TYPE_DATE    = 'date';
}
最后,创建所有需要的类,扩展
Attribute
类并实现
getType()
方法

/**
 * TextAttribute
 *
 * @ORM\Entity
 */
class TextAttribute extends Attribute
{
    public function getType()
    {
        return $this::TYPE_TEXT;
    }
}

/**
 * BooleanAttribute
 *
 * @ORM\Entity
 */
class BooleanAttribute extends Attribute
{
    public function getType()
    {
        return $this::TYPE_BOOLEAN;
    }
}

/**
 * NumericAttribute
 *
 * @ORM\Entity
 */
class  NumericAttribute extends Attribute
{
    public function getType()
    {
        return $this::TYPE_NUMERIC;
    }
}

/**
 * DateAttribute
 *
 * @ORM\Entity
 */
class DateAttribute extends Attribute
{
    public function getType()
    {
        return $this::TYPE_DATE;
    }
}

// And so on...

与在每个子级中重载方法或在每个子级中定义常量相比,另一种更灵活、更快的方法是使用反射类检索不带命名空间的类的名称:

public function getType() {
    return (new \ReflectionClass($this))->getShortName();
}
它也适用于自PHP5以来的任何php版本

根据您的鉴别器映射声明,它可能不会准确返回鉴别器名称,但它将返回子实体名称(类名),这是命名和区分不同子实体的好方法


无需在子类中定义任何内容。

这实际上并不访问鉴别器字段,它只是假装访问。考虑一个具有相同类别的多个值的鉴别器映射,但是你需要从数据库中得到的实际值,而不是猜测它应该是哪一个值。当多个鉴别器值映射到同一个类时,情况如何?我正在将一些项目迁移到Symfony,有5种类型(类常量)映射到2个类(由一个数据库字段水合,如discriminator)。代码的其他部分依赖于
MappedObject::getType()
vs类常量比较,因此,我需要鉴别器值,或者我必须为每个鉴别器的值重构具有唯一类的代码库…可能重复的注意,在php5.3中,
get_called_class
调用是不必要的,您可以使用
static
关键字,例如:
return static::TYPE
,对于我的情况,这是最好的方法。我没有地图。类型将是小写的类名。所以我可以将我的图像(文件)放入不同的文件夹中,比如:公共函数getFullPath():?string{return$this->getType()。“/”$this->getFolder()。$this->getFilename();}公共函数getType():string{return strtolower((new\ReflectionClass($this))->getShortName();}