web-dev-qa-db-ja.com

doctrine2のphpからdiscriminatorフィールドにアクセスできますか?

次のような継承を定義するエンティティがあります。

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

フィールド「タイプ」のゲッターを持つことは可能ですか?私はinstanceofを使用できることを知っています(そしてほとんどの場合これが私がやっていることです)が、$ item-> getType()が私の人生をとても楽にしてくれるシナリオはほとんどありません。

25
Greg

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;
    }
}
20
xPheRe

これが私のやり方です。

まず、AttributeInterfaceを作成して、将来のすべての新しい属性タイプが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...
_
14
ByScripts

EntityManagerまたはDocumentManagerのいずれかを使用して可能です。

$documentManager->getClassMetadata(get_class($entity))->discriminatorValue;
11
Lakatos Gyula

私のアプローチは、メタデータを介してその値にアクセスすることですdoctrine generate

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

基本エンティティを拡張する各クラスの静的変数にメタデータをキャッシュします。そこには他にも多くの有用な情報があります...

8
user2272605

いいえ、それは不可能ですが、次のようなことができます:get_class($ object)== TYPE_CONST

4
beberlei

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
}
4
Yaron

私のように、constの使用を避けたい場合は、このようなものを使用してください。

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

    return end($type);
}
3
dizda

すべての子でメソッドをオーバーロードしたり、すべての子で定数を定義したりするよりも滑らかで高速な別の方法は、リフレクションクラスを使用して、名前空間なしでクラスの名前を取得することです。

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

また、php5以降のすべてのphpバージョンで機能します

弁別子マップ宣言によっては、弁別子名を正確に返さない場合がありますが、子エンティティ名(クラス名)が返されます。これは、さまざまなサブエンティティに名前を付けて区別するための優れた方法です。

サブクラスで何も定義する必要はありません。

1
Tofandel