Могу ли я получить доступ к поля дискриминатора из php в doctrine2?
У меня есть сущность, которая определяет наследование следующим образом:
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"text" = "TextAttribute", "boolean" = "BooleanAttribute", "numeric" = "NumericAttribute", "date" = "DateAttribute"})
Мне интересно, возможно ли получить getter для типа поля? Я знаю, что могу использовать instanceof (и в большинстве случаев это то, что я делаю), но есть несколько сценариев, в которых $item- > getType() облегчит мне жизнь.
Ответы
Ответ 1
Расширяя сказанное 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;
}
}
Ответ 2
Вот как я это сделал.
Сначала вы создали AttributeInterface
, чтобы убедиться, что все будущие новые типы атрибутов будут реализовывать метод необходимости:
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...
Ответ 3
Это возможно либо с помощью EntityManager, либо с помощью DocumentManager.
$documentManager->getClassMetadata(get_class($entity))->discriminatorValue;
Ответ 4
Мой подход состоит в том, чтобы просто получить доступ к этому значению через доктрину метаданных, генерирующую
$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;
}
Я кэширую метаданные в статической переменной для каждого класса, который расширяет мою базовую сущность, есть много другой полезной информации...
Ответ 5
Нет, это невозможно, но вы можете сделать что-то вроде: get_class ($ object) == TYPE_CONST
Ответ 6
В 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
Используйте что-то вроде этого, если хотите, как и я, избегать использования константы:
public function getType()
{
$type = explode('\\', get_class($this));
return end($type);
}
Ответ 8
Еще один способ сглаживания, чем перегрузить метод в каждом дочернем элементе с помощью собственного symfony:
public function getType() {
return (new \ReflectionClass($this))->getShortName();
}
Он может не возвращать точно имя дискриминатора в зависимости от вашего объявления карты дискриминатора, но он вернет имя дочернего объекта (имя класса), которое является отличным способом назвать и выделить разные сущности
Без необходимости определять что-либо в подклассах.