2010-12-15 4 views
19

Mam podmiot, który określa dziedziczenia tak:Czy mogę uzyskać dostęp do pola dyskryminatora z php w doctrine2?

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

Zastanawiam się czy to możliwe, aby mieć getter dla pola „typ”? Wiem, że mogę użyć instanceof (w większości przypadków to jest to, co robię), ale jest kilka scenariuszy, w których $ item-> getType() znacznie ułatwiłoby mi życie.

+0

Możliwy duplikat [Mapuj kolumnę dyskryminatora do pola z Doctrine 2] (https://stackoverflow.com/questions/21284964/map-a-discriminator-column-to-a-field-with-doctrine-2) – sroes

Odpowiedz

13

Rozszerzanie co beberlei powiedział, można zadeklarować kilka stałych klasy atrybutu i abstrakcyjnej getType() funkcję. Następnie przeciąż go w każdej wyprowadzonej klasie atrybutów.

Coś jak:

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

Nie jest to niemożliwe, ale można zrobić coś takiego: get_class ($ object) == TYPE_CONST

+0

Co powiesz na przypadki, gdy wiele wartości dyskryminatora jest odwzorowanych na tę samą klasę? Przenoszę jakiś projekt do Symfony i istnieje 5 typów (stałych klasowych) zmapowanych do 2 klas (uwodnionych przez jedno pole bazy danych, takie jak dyskryminator). Inne części kodu opierają się na 'MappedObject :: getType()' vs porównaniu stałej klasy, więc potrzebuję wartości dyskryminatora lub muszę korygować kod z unikalnymi klasami dla każdej wartości dyskryminatora ... – Wirone

3

użyć czegoś takiego, jeśli chcesz, tak jak ja, należy unikać używania const:

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

    return end($type); 
} 
4

Jest zręczny sposób to zrobić w 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 
} 
6

Moje podejście polega na uzyskaniu dostępu do jego wartości poprzez doktrynę metadanych generującą

$cmf = $em->getMetadataFactory(); 
$meta = $cmf->getMetadataFor($class); 
$meta->discriminatorValue 

daje wartość, tak jak metoda

public static function get_type() 
{ 
    //...get the $em instance 
    $cmf = $em->getMetadataFactory(); 
    $meta = $cmf->getMetadataFor(__CLASS__); 
    return $meta->discriminatorValue; 
} 

I buforować metadane w statycznej zmiennej dla każdej klasy, która rozciąga się moją jednostkę bazową, istnieje wiele innych przydatnych informacji w tam również ...

9

Jest to możliwe z EntityManager lub za pomocą DocumentManager.

$documentManager->getClassMetadata(get_class($entity))->discriminatorValue; 
13

Oto, jak to zrobię.

pierwsze, dokonał AttributeInterface, aby mieć pewność, że w przyszłości wszystkie nowe typy atrybut będzie wdrożyć metody potrzebne:

interface AttributeInterface 
{ 
    /** 
    * Return the attribute type 
    */ 
    public function getType(); 
} 

Następnie należy utworzyć Attribute klasa abstrakcyjna wykonawczych interfejsu AttributeInterface.

użyć stałych w zaproszeniu @DiscrimatorMap jakiegoś konsystencji

/** 
* 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'; 
} 

Wreszcie, należy utworzyć wszystkie potrzebne lekcje, rozszerzając Attribute klasę i wdrożenie metody 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

To nie ma dostępu do pola dyskryminatora , po prostu udaje. Rozważ mapę dyskryminatora, która ma wiele wartości dla tej samej klasy, ale potrzebujesz rzeczywistej wartości z bazy danych, a nie zgadywania, która wartość powinna być. –

0

Innym płaszcz sposób niż do przeciążenia metoda dla każdego dziecka, z natywną symfonią:

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

To może nie wrócić dokładnie nazwę dyskryminatora zależności od dyskryminatora deklaracji mapie, ale powróci nazwę podmiotu dziecko (nazwa klasy), które jest doskonałym sposobem na imię i odróżnienia różnych subentities

bez konieczności zdefiniuj cokolwiek w podklasach.

Powiązane problemy