2015-11-30 13 views
5

के साथ स्वयं-संदर्भ, मेरे पास सामान्य संबंधों और विशेषताओं के साथ कुछ entites हैं। इसलिए, मैं विरासत मैपिंग का उपयोग करके अपनी स्कीमा को सरल बनाना चाहता हूं।कई से एक, विरासत मानचित्रण

मैंने बेसडाटा मैपडेस्परक्लास बनाया है, और मेरी अन्य इकाइयां इसे विस्तारित करती हैं। इस बेसडाटा कक्षा में प्रत्येक इकाई में आवश्यक सामान्य संबंध हैं।

यह कई-से-एक संबंध के साथ काम करता है,

/** 
* @ORM\MappedSuperclass 
*/ 
class BaseData 
{ 

    /** 
    * @ORM\ManyToOne(targetEntity="Service") 
    * @ORM\JoinColumn(name="service_id", referencedColumnName="id") 
    */ 
    protected $service; 

की तरह लेकिन यह एक छोटा सा स्वत: संदर्भ के साथ और अधिक मुश्किल हो गया है।

/** 
* @ORM\MappedSuperclass 
*/ 
class BaseData 
{ 

    /** 
    * @ORM\ManyToOne(targetEntity="BaseData") 
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true) 
    */ 
    protected $parent; 

जाहिर है, यह एक TableNotFoundException के लिए नेतृत्व जब मैं इस इकाई क्वेरी करने के लिए प्रयास करें:: QLSTATE[42S02]: Base table or view not found: 1146 Table 'project.base_data' doesn't exist

उदाहरण के लिए, के बाद से मैं एक माता पिता के संदर्भ बनाना चाहते हैं, मुझे लगता है कि कोशिश की।

तो, मैंने एसोसिएशन ओवरराइड की कोशिश की, लेकिन ऐसा लगता है कि लक्ष्य इकाई को बदलने की अनुमति नहीं है।

तो, क्या मैपडसुपरक्लास पर कुछ आत्म-संदर्भ बनाने का कोई तरीका है? और वैसे, क्या यह भी समझ में आता है?

अग्रिम में बहुत धन्यवाद!

मैं योजना के अनुसार मेरी BaseData mappedSuperClass में protected $parent और protected $children परिभाषित:

अद्यतन

यहाँ anwser है। मैंने उन्हें आवश्यक अन्य जानकारी के साथ टिप्पणी की। उदाहरण:

/** 
* @ORM\MappedSuperclass 
*/ 
class BaseData 
{ 

    /** 
    * @Datagrid\Column(field="parent.id", title="datagrid.parent_id", visible=false, safe=false) 
    * @Serializer\Expose 
    * @Serializer\Groups({"foo"}) 
    */ 
    protected $parent; 

    /** 
    * @Serializer\Expose 
    * @Serializer\Groups({"elastica"}) 
    */ 
    protected $children; 

फिर, मैं ईवेंट loadClassMetadata के साथ ओआरएम संबंध जोड़ता हूं।

/** 
* @param LoadClassMetadataEventArgs $eventArgs 
*/ 
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) 
{ 
    // the $metadata is all the mapping info for this class 
    $classMetadata = $eventArgs->getClassMetadata(); 
    $reflObj = new \ReflectionClass($classMetadata->name); 
    if($reflObj) { 
     if ($reflObj->isSubclassOf('CoreBundle\Entity\BaseData')) { 
      $fieldMapping = array(
       'targetEntity' => $classMetadata->name, 
       'fieldName'  => 'parent', 
       'inversedBy' => 'children', 
       'JoinColumn' => array(
        'name'     => 'parent_id', 
        'referencedColumnName' => 'id', 
        'nullable'    => true, 
        'onDelete'    => 'SET NULL', 
       ), 
      ); 

      $classMetadata->mapManyToOne($fieldMapping); 


      $fieldMapping = array(
       'fieldName'  => 'children', 
       'targetEntity' => $classMetadata->name, 
       'mappedBy'  => 'parent', 
      ); 
      $classMetadata->mapOneToMany($fieldMapping); 
     } 
    } 
} 

ईवेंट पंजीकृत करें, और यही वह है।

अब, बेसडाटा सुपरक्लास को विस्तारित करने वाली प्रत्येक कक्षा संबंध प्राप्त करती है। उदाहरण के लिए, php app/console doctrine:generate:entities MyBundle इच्छा उपवर्ग इकाई के अंदर निम्नलिखित कोड उत्पन्न करता है:

/** 
* Set parent 
* 
* @param \MyBundle\Entity\Subclass $parent 
* 
* @return Subclass 
*/ 
public function setParent(\MyBundle\Entity\Subclass $parent = null) 
{ 
    $this->parent = $parent; 

    return $this; 
} 

/** 
* Get parent 
* 
* @return \MyBundle\Entity\Subclass 
*/ 
public function getParent() 
{ 
    return $this->parent; 
} 

/** 
* Add child 
* 
* @param \MyBundle\Entity\Subclass $child 
* 
* @return Subclass 
*/ 
public function addChild(\MyBundle\Entity\Subclass $child) 
{ 
    $this->children[] = $child; 

    return $this; 
} 

/** 
* Remove child 
* 
* @param \MyBundle\Entity\Subclass $child 
*/ 
public function removeChild(\MyBundle\Entity\Subclass $child) 
{ 
    $this->children->removeElement($child); 
} 

/** 
* Get children 
* 
* @return \Doctrine\Common\Collections\Collection 
*/ 
public function getChildren() 
{ 
    return $this->children; 
} 
+0

देखें आप बच्चे कक्षाओं के लिए केवल आत्म संदर्भ के रूप में कर सकता है MappedSupperclass एक इकाई ही नहीं है। दस्तावेज़ों से: एक मैप किए गए सुपरक्लास एक इकाई नहीं हो सकता है, यह मैप किए गए सुपरक्लास द्वारा परिभाषित क्वेरी-सक्षम और लगातार संबंध नहीं होना चाहिए (केवल एक स्वामित्व पक्ष के साथ)। इसका मतलब है कि एक मैप किए गए सुपरक्लास पर एक से कई संगठन संभव नहीं हैं।इसके अलावा कई से कई संगठन केवल तभी संभव होते हैं जब मैप किए गए सुपरक्लास का उपयोग केवल इस समय एक इकाई में किया जाता है। –

+0

मैंने वास्तव में अनुमान लगाया, लेकिन मेरा लक्ष्य प्रत्येक बच्चे वर्गों के लिए आत्म-संदर्भ काम करना था। मेरा मतलब है, 'targetEntity = "BaseData" लिखकर, मैं उम्मीद कर रहा था कि हर बच्चे वर्ग अपने नाम का उपयोग करने जा रहा था। तो, मुझे लगता है, मुझे प्रत्येक बच्चे कक्षाओं में माता-पिता को स्वयं-संदर्भ मैन्युअल रूप से बनाना है, है ना? और आपकी मदद के लिए धन्यवाद। – TiPi

+1

कोई समस्या नहीं! चूंकि @ मैप्डसुपरक्लास एक इकाई नहीं है, हां, मुझे लगता है, आप केवल बाल कक्षाओं में ही ऐसा कर सकते हैं। अनुलेख IMHO, @MappedSuperclass सभी प्रकार के शब्दकोशों के लिए बहुत उपयोगी है - आखिरी प्रोजेक्ट में, उदाहरण के लिए, मेरे पास एक बेस डिक्शनरी दस्तावेज़ था, जिसमें दो फ़ील्ड आईडी और sysName थे। और सभी शब्दकोश सिर्फ 'क्लास BlahBlahDocument जैसा दिख रहे थे BaseDictionaryDocument {} 'और, ज़ाहिर है, शीर्ष पर तालिका/संग्रह नाम के साथ एक टिप्पणी। –

उत्तर

2

आप मानचित्रण @ORM\ManyToOne(targetEntity="BaseData") हटाने और घटना loadClassMetadata पर एक घटना श्रोता बना सकते हैं। इस तरह (मैं निम्नलिखित कोड का परीक्षण नहीं किया है, यह सिर्फ एक प्रारंभिक बिंदु है) कुछ: सूचना के लिए

class TestEvent 
{ 
    public function loadClassMetadata(\Doctrine\ORM\Event\LoadClassMetadataEventArgs $eventArgs) 
    { 
     $classMetadata = $eventArgs->getClassMetadata(); 
     $class = $classMetadata->getName(); 
     $fieldMapping = array(
      'fieldName' => 'parent', 
      'targetEntity' => $class, 
     ); 
     $classMetadata->mapManyToOne($fieldMapping); 
    } 
} 

एक महत्वपूर्ण बात यह है कि एक श्रोता अपने आवेदन में सभी संस्थाओं के लिए सुन रहा हो जाएगा।

Doctrine docs about events और How to register event listener in symfony2

+0

मैंने आपके समाधान की कोशिश की, और इसे काम करने में कामयाब रहा जैसा मैं चाहता था। मैं anwser को एकीकृत करने के लिए अपना प्रश्न अपडेट करूंगा। – TiPi

+0

मुझे खुशी है कि इससे मदद मिली –

संबंधित मुद्दे