可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have an entity which defines inheritance like this:
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"text" = "TextAttribute", "boolean" = "BooleanAttribute", "numeric" = "NumericAttribute", "date" = "DateAttribute"})
I am wondering is it possible to have getter for field 'type'? I know I can use instanceof (and in most cases this is what I'm doing) but there are few scenarios where $item->getType() would make my life so much easier.
回答1:
Extending what beberlei said, you could declare some constants in the Attribute class, and an abstract getType()
function. Then, overload it in every derived attribute class.
Something like:
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;
}
}
回答2:
Here is how I'd do.
First, you made an AttributeInterface
, to be sure that all future new Attribute types will implement the need method :
interface AttributeInterface
{
/**
* Return the attribute type
*/
public function getType();
}
Then you create the Attribute
abstract class implementing the AttributeInterface
interface.
Use the constants in the @DiscrimatorMap
call for some consistency
/**
* 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';
}
Finally, you create all needed classes, extending Attribute
class and implementing the getType()
method
/**
* 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...
回答3:
It's possible either with the EntityManager or using the DocumentManager.
$documentManager->getClassMetadata(get_class($entity))->discriminatorValue;
回答4:
My approach is to simply access it's value through the meta data doctrine generates
$cmf = $em->getMetadataFactory();
$meta = $cmf->getMetadataFor($class);
$meta->discriminatorValue
will give you the value, so as a method
public static function get_type()
{
//...get the $em instance
$cmf = $em->getMetadataFactory();
$meta = $cmf->getMetadataFor(__CLASS__);
return $meta->discriminatorValue;
}
I cache the metadata in a static variable for each class that extends my base entity, there is a lot of other useful information in there as well ...
回答5:
No that is not possible, but you can do something like: get_class($object) == TYPE_CONST
回答6:
There's a slicker way to do it in 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
}
回答7:
Use something like this if you want, like me, avoid use of const :
public function getType()
{
$type = explode('\\', get_class($this));
return end($type);
}
回答8:
Another slicker way than to overload the method in every child, with native symfony :
public function getType() {
return (new \ReflectionClass($this))->getShortName();
}
It might not return exactly the discriminator name depending on your discriminator map declaration but it will return the child entity name (the class name) which is a great way to name and distinguish the different subentities
Without a need to define anything in the subclasses.