次のような継承を定義するエンティティがあります。
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"text" = "TextAttribute", "boolean" = "BooleanAttribute", "numeric" = "NumericAttribute", "date" = "DateAttribute"})
フィールド「タイプ」のゲッターを持つことは可能ですか?私はinstanceofを使用できることを知っています(そしてほとんどの場合これが私がやっていることです)が、$ item-> getType()が私の人生をとても楽にしてくれるシナリオはほとんどありません。
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;
}
}
これが私のやり方です。
まず、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...
_
EntityManagerまたはDocumentManagerのいずれかを使用して可能です。
$documentManager->getClassMetadata(get_class($entity))->discriminatorValue;
私のアプローチは、メタデータを介してその値にアクセスすることです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;
}
基本エンティティを拡張する各クラスの静的変数にメタデータをキャッシュします。そこには他にも多くの有用な情報があります...
いいえ、それは不可能ですが、次のようなことができます:get_class($ object)== TYPE_CONST
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
}
私のように、constの使用を避けたい場合は、このようなものを使用してください。
public function getType()
{
$type = explode('\\', get_class($this));
return end($type);
}
すべての子でメソッドをオーバーロードしたり、すべての子で定数を定義したりするよりも滑らかで高速な別の方法は、リフレクションクラスを使用して、名前空間なしでクラスの名前を取得することです。
public function getType() {
return (new \ReflectionClass($this))->getShortName();
}
また、php5以降のすべてのphpバージョンで機能します
弁別子マップ宣言によっては、弁別子名を正確に返さない場合がありますが、子エンティティ名(クラス名)が返されます。これは、さまざまなサブエンティティに名前を付けて区別するための優れた方法です。
サブクラスで何も定義する必要はありません。