Ho un'entity framework; che definisce l'ereditarietà come questa:
* @DiscriminatorColumn(name="type", type="string") * @DiscriminatorMap({"text" = "TextAttribute", "boolean" = "BooleanAttribute", "numbersc" = "NumericAttribute", "date" = "DateAttribute"})
Mi chiedo se sia ansible avere getter per il field 'tipo'? So che posso usare instanceof (e nella maggior parte dei casi questo è quello che sto facendo) ma ci sono pochi scenari in cui $ item-> getType () renderebbe la mia vita molto più facile.
Estendendo quanto detto da beberlei, è ansible dichiarare alcune costanti nella class Attribute e una function astratta getType()
. Quindi, sovraccaricarlo in each class di attributi derivata.
Qualcosa di simile a:
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; } }
Ecco come farei.
Innanzitutto, hai creato una AttributeInterface
, per essere sicuro che tutti i futuri nuovi tipi di Attributo implementeranno il metodo della necessità:
interface AttributeInterface { /** * Return the attribute type */ public function getType(); }
Quindi si crea la class astratta Attribute
implementa l'interface AttributeInterface
.
Utilizzare le costanti nella chiamata @DiscrimatorMap
per una certa coerenza
/** * 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 = 'numbersc'; const TYPE_DATE = 'date'; }
Infine, crei tutte le classi necessarie, estendendo la class Attribute
e implementando il metodo 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...
È ansible con EntityManager o utilizzando DocumentManager.
$documentManager->getClassMetadata(get_class($entity))->discriminatorValue;
Il mio approccio è quello di accedere semplicemente al suo valore attraverso la doctrine dei metadati
$cmf = $em->getMetadataFactory(); $meta = $cmf->getMetadataFor($class); $meta->discriminatorValue
ti darà il valore, quindi come metodo
public static function get_type() { //...get the $em instance $cmf = $em->getMetadataFactory(); $meta = $cmf->getMetadataFor(__CLASS__); return $meta->discriminatorValue; }
Metto in cache i metadati in una variabile statica per each class che estende la mia entity framework; di base, ci sono anche molte altre informazioni utili …
No, non è ansible, ma puoi fare qualcosa del tipo: get_class ($ object) == TYPE_CONST
C'è un modo semplice per farlo 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 }
Usa qualcosa di simile se vuoi, come me, evitare l'uso di const:
public function getType() { $type = explode('\\', get_class($this)); return end($type); }
Un altro modo per sfogliare che sovraccaricare il metodo in each bambino, con symfony nativo:
public function getType() { return (new \ReflectionClass($this))->getShortName(); }
Potrebbe non restituire esattamente il nome del discriminatore in base alla dichiarazione della mappa discriminatore, ma restituirà il nome dell'entity framework; figlio (il nome della class) che è un ottimo modo per nominare e distinguere le diverse sottoentity framework;
Senza la necessità di definire nulla nelle sottoclassi.