2016-04-18 7 views
0

Für ein Projekt muss ich "Karten" verwalten. Es gibt zwei Kartentypen: "Kundenkarte" und "Mitgliedskarte". Karten können von einem Benutzer dieser Anwendung bestellt werden.Doctrine2/Abfrage Diskriminator Wert

Um dies zu erreichen, schuf ich eine abstrakte Card Einheit mit einem Type Diskriminator.

/* @ORM\Entity 
* @ORM\Table(name="cards") 
* @ORM\InheritanceType("SINGLE_TABLE") 
* @ORM\DiscriminatorColumn(name="type", type="string") 
* @ORM\DiscriminatorMap({"member"="MemberCard", "client"="ClientCard"}) 
*/ 
abstract class Card 
{ 
    const MEMBER = 'member'; 
    const CLIENT = 'client'; 

    /** 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="IDENTITY") 
    * @ORM\Column(type="integer") 
    */ 
    protected $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="CardsOrder", inversedBy="cards") 
    * @ORM\JoinColumn(name="order_id", referencedColumnName="id", onDelete="CASCADE") 
    */ 
    protected $order; 

    /** 
    * Return the card type 
    * 
    * @return string 
    */ 
    abstract public function getType(); 

    /** 
    * @return mixed 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * @param CardsOrder $order 
    * 
    * @return $this 
    */ 
    public function setOrder(CardsOrder $order) 
    { 
     $this->order = $order; 

     return $this; 
    } 

    /** 
    * @return CardsOrder 
    */ 
    public function getOrder() 
    { 
     return $this->order; 
    } 
} 

Die MemberCard Einheit

/** 
* @ORM\Entity 
*/ 
class MemberCard extends Card 
{ 

    /** 
    * @ORM\ManyToOne(targetEntity="Member", inversedBy="cards") 
    * @ORM\JoinColumn(name="member_id", referencedColumnName="id", onDelete="CASCADE") 
    */ 
    protected $member; 

    /** 
    * @param Member $member 
    * 
    * @return $this 
    */ 
    public function setMember(Member $member) 
    { 
     $this->member = $member; 

     return $this; 
    } 

    /** 
    * @return Member 
    */ 
    public function getMember() 
    { 
     return $this->member; 
    } 

    /** 
    * @return string 
    */ 
    public function getType() 
    { 
     return self::MEMBER; 
    } 
} 

Die ClientCard Einheit

/** 
* @ORM\Entity 
*/ 
class ClientCard extends Card 
{ 

    /** 
    * ClientCard - client n-1 relation 
    * 
    * @ORM\ManyToOne(targetEntity="Client", inversedBy="cards") 
    * @ORM\JoinColumn(name="client_id", referencedColumnName="id", onDelete="CASCADE") 
    */ 
    protected $client; 

    /** 
    * @param \Admin\Crm\Entity\Client\Client $client 
    * 
    * @return $this 
    */ 
    public function setClient(Client $client) 
    { 
     $this->client = $client; 

     return $this; 
    } 

    /** 
    * @return Client 
    */ 
    public function getClient() 
    { 
     return $this->client; 
    } 

    /** 
    * @return string 
    */ 
    public function getType() 
    { 
     return self::CLIENT; 
    } 

} 

Jetzt möchte ich, wenn ein Mitglied oder ein Kunde wissen, eine anhängige bestellte Karte hat (Status ein binäres Status Flagge):

public function findPendingCard($clientOrMember) 
{ 
    // $this->getRepository is the Card repository, injected in a factory 
    $query = $this->getRepository()->createQueryBuilder('c') 
         ->join('c.order', 'o', 'WITH', 'BIT_AND(o.status, :oStatus) > 0') 
         ->where('c INSTANCE OF :memberCardEntity AND c.member = :clientOrMember') 
         ->orWhere('c INSTANCE OF :clientCardEntity AND c.client = :clientOrMember') 
         ->setParameters([ 
          'oStatus'  => CardsOrder::OPEN, 
          'clientOrMember' => $clientOrMember, 
          'memberCardEntity' => MemberCard::class, 
          'clientCardEntity' => ClientCard::class, 
         ]) 
         ->getQuery(); 

     return $query->getOneOrNullResult(); 
    } 

Aber ich habe diesen Fehler:

[Semantical Error] line 0, col 148 near 'member = :clientOrMember)': Error: Class Card has no field or association named member 

Jede Idee, was mache ich falsch?

Antwort

1

Es ist nicht so sehr, dass Sie etwas falsch machen, aber es gibt eine Methode, um das Problem zu umgehen. Sie können den Kartentyp wie folgt zurückgeben.

In Klasse-Karte add:

public function getCardType() 
{ 
    return $this->discr; 
} 

in der Klasse MEMBER hinzufügen:

protected $discr = 'member'; 

in der Klasse ClientCard hinzufügen:

protected $discr = 'client'; 
+0

@ geoB, vielen Dank für diesen sehr großen und nützlichen Trick ! Es wird mir sehr helfen und ich muss die Entity-Instanz nicht mehr überprüfen. Aber wie überprüft man den Wert von 'MemberCard :: $ member' oder' ClientCard :: $ member'? Wenn ich diese Abfrage in SQL schreiben sollte, scheint es, SELECT * von Karten c JOIN card_orders o ON (c.order_id = o.id) WHERE ((c.type = 'Mitglied' AND c.member_id =?) ODER (c.type = 'client' AND c.client_id =?)) .... ' – ceadreak

+0

Was passiert mit Ihrer Anfrage (angenommen' type' == 'discr')? – geoB

+0

Ja, geben Sie discr ein. Die Abfrage ist richtig, aber die Frage ist, wie man diesen Teil mit dem Query Builder über das Repository 'Card' schreibt:' c.member_id =? '...' c.client_id =? 'Weil' member' und 'client' nicht sind direkte Eigenschaften von der abstrakten Entität "Card", aber untergeordnete Eigenschaften – ceadreak

Verwandte Themen