31

我有一个定义继承的实体,如下所示:

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

我想知道是否可以为字段“类型”设置吸气剂?我知道我可以使用 instanceof (在大多数情况下,这就是我正在做的事情),但在少数情况下 $item->getType() 会让我的生活变得如此轻松。

4

8 回答 8

24

扩展 beberlei 所说的,您可以在 Attribute 类中声明一些常量,以及一个抽象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;
    }
}
于 2010-12-27T08:23:32.857 回答
17

这是我的做法。

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

interface AttributeInterface
{
    /**
     * Return the attribute type
     */
    public function getType();
}

然后创建实现接口的Attribute抽象类。AttributeInterface

使用@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...
于 2014-02-11T11:45:15.690 回答
12

可以使用 EntityManager 或使用 DocumentManager。

$documentManager->getClassMetadata(get_class($entity))->discriminatorValue;
于 2014-01-09T13:15:31.237 回答
8

我的方法是通过生成的元数据原则简单地访问它的价值

$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;
}

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

于 2013-06-25T20:28:40.850 回答
4

在 PHP 5.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
}
于 2013-06-19T01:27:51.297 回答
4

不,这是不可能的,但你可以这样做: get_class($object) == TYPE_CONST

于 2010-12-16T15:24:33.863 回答
3

如果你想使用这样的东西,像我一样,避免使用 const :

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

    return end($type);
}
于 2013-04-11T19:41:28.337 回答
3

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

public function getType() {
    return (new \ReflectionClass($this))->getShortName();
}

它也适用于自 php 5 以来的任何 php 版本

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

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

于 2017-06-27T11:45:15.227 回答