2010-12-15 12 views
19

que tienen una entidad que define la herencia de esta manera:¿Puedo acceder al campo del discriminador desde php en doctrine2?

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

Me pregunto ¿es posible tener captador para el campo 'tipo'? Sé que puedo usar instanceof (y en la mayoría de los casos esto es lo que estoy haciendo) pero hay pocos escenarios donde $ item-> getType() haría mi vida mucho más fácil.

+0

Posible duplicado de [Asignar una columna de discriminador a un campo con Doctrine 2] (https://stackoverflow.com/questions/21284964/map-a-discriminator-column-to-a-field-with-doctrine-2) – sroes

Respuesta

13

Extendiendo lo beberlei dicho, usted podría declarar algunas constantes de la clase de atributo, y una función abstracta getType(). Luego, sobrecargalo en cada clase de atributo derivado.

Algo así como:

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

Sin eso no es posible, pero se puede hacer algo como: get_class ($ objeto) == TYPE_CONST

+0

¿Qué ocurre con los casos en los que se correlacionan varios valores de discriminación en la misma clase? Estoy migrando un proyecto a Symfony y hay 5 tipos (constantes de clase) asignados a 2 clases (hidratados por un campo de base de datos, como discriminador). Otras partes del código se basan en 'MappedObject :: getType()' frente a la constante de clase, por lo que necesito un valor de discriminación o tengo que refactorizar la base de código con clases únicas para el valor de cada discriminador ... – Wirone

3

usar algo como esto si quieres, como yo, evitar el uso de const:

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

    return end($type); 
} 
4

Hay una manera más pulido para hacerlo en 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

Mi enfoque es simplemente acceder a su valor a través de la doctrina de metadatos genera

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

le dará el valor, así como un método

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

que almacenar en caché los metadatos en una variable estática para cada clase que extienda mi entidad de base, hay una gran cantidad de información útil en allí también ...

9

Es posible con EntityManager o con DocumentManager.

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

Así es como lo haría.

En primer lugar, usted hizo una AttributeInterface, para asegurarse de que todos los futuros nuevos tipos de atributos implementarán el método de necesidad:

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

a continuación, crear la clase abstracta que implementa la interfaz AttributeAttributeInterface.

utilizar las constantes en la llamada @DiscrimatorMap a una cierta coherencia

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

Por último, se crea todas las clases necesarias, que se extiende Attribute clase y la realización del procedimiento 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

Esto realmente no tiene acceso al campo discriminador , solo pretende hacerlo. Considere un mapa discriminador que tiene múltiples valores para la misma clase, pero necesita el valor real de la base de datos y no adivinar qué valor debería ser. –

0

Otra forma de pulido que a la sobrecarga el método en cada niño, con symfony nativo:

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

Podría no volver exactamente con el nombre discriminador dependiendo de su declaración mapa discriminador pero va a devolver el nombre de la entidad hijo (el nombre de la clase), que es una gran manera de nombrar y distinguir los diferentes subentidades

Sin necesidad de define cualquier cosa en las subclases.

Cuestiones relacionadas