Doctrine2: संदर्भ तालिका में अतिरिक्त स्तंभों के साथ कई-से-कई को संभालने का सबसे अच्छा तरीका है


282

मैं सोच रहा हूं कि Doctrine2 में कई-से-कई संबंधों के साथ काम करने का सबसे अच्छा, सबसे साफ और सबसे सरल तरीका क्या है।

मान लेते हैं कि हमें मेटालिका द्वारा मास्टर ऑफ़ पपेट्स जैसा एक एल्बम मिला है जिसमें कई ट्रैक हैं। लेकिन कृपया इस तथ्य पर ध्यान दें कि एक ट्रैक अधिक दिखाई दे सकता है जिसमें एक एल्बम, जैसे बैटरी बाय मेटालिका करता है - तीन एल्बम इस ट्रैक की विशेषता हैं।

इसलिए मुझे कुछ अतिरिक्त स्तंभों (जैसे निर्दिष्ट स्थान में ट्रैक की स्थिति) के साथ तीसरी तालिका का उपयोग करके एल्बम और पटरियों के बीच कई-से-कई संबंध चाहिए। वास्तव में मुझे उपयोग करना है, जैसा कि डॉक्ट्रिन के दस्तावेज से पता चलता है, उस कार्यक्षमता को प्राप्त करने के लिए एक डबल-टू-कई संबंध।

/** @Entity() */
class Album {
    /** @Id @Column(type="integer") */
    protected $id;

    /** @Column() */
    protected $title;

    /** @OneToMany(targetEntity="AlbumTrackReference", mappedBy="album") */
    protected $tracklist;

    public function __construct() {
        $this->tracklist = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function getTitle() {
        return $this->title;
    }

    public function getTracklist() {
        return $this->tracklist->toArray();
    }
}

/** @Entity() */
class Track {
    /** @Id @Column(type="integer") */
    protected $id;

    /** @Column() */
    protected $title;

    /** @Column(type="time") */
    protected $duration;

    /** @OneToMany(targetEntity="AlbumTrackReference", mappedBy="track") */
    protected $albumsFeaturingThisTrack; // btw: any idea how to name this relation? :)

    public function getTitle() {
        return $this->title;
    }

    public function getDuration() {
        return $this->duration;
    }
}

/** @Entity() */
class AlbumTrackReference {
    /** @Id @Column(type="integer") */
    protected $id;

    /** @ManyToOne(targetEntity="Album", inversedBy="tracklist") */
    protected $album;

    /** @ManyToOne(targetEntity="Track", inversedBy="albumsFeaturingThisTrack") */
    protected $track;

    /** @Column(type="integer") */
    protected $position;

    /** @Column(type="boolean") */
    protected $isPromoted;

    public function getPosition() {
        return $this->position;
    }

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

    public function getAlbum() {
        return $this->album;
    }

    public function getTrack() {
        return $this->track;
    }
}

नमूना डेटा:

             Album
+----+--------------------------+
| id | title                    |
+----+--------------------------+
|  1 | Master of Puppets        |
|  2 | The Metallica Collection |
+----+--------------------------+

               Track
+----+----------------------+----------+
| id | title                | duration |
+----+----------------------+----------+
|  1 | Battery              | 00:05:13 |
|  2 | Nothing Else Matters | 00:06:29 |
|  3 | Damage Inc.          | 00:05:33 |
+----+----------------------+----------+

              AlbumTrackReference
+----+----------+----------+----------+------------+
| id | album_id | track_id | position | isPromoted |
+----+----------+----------+----------+------------+
|  1 |        1 |        2 |        2 |          1 |
|  2 |        1 |        3 |        1 |          0 |
|  3 |        1 |        1 |        3 |          0 |
|  4 |        2 |        2 |        1 |          0 |
+----+----------+----------+----------+------------+

अब मैं एल्बम और उनसे जुड़ी पटरियों की एक सूची प्रदर्शित कर सकता हूं:

$dql = '
    SELECT   a, tl, t
    FROM     Entity\Album a
    JOIN     a.tracklist tl
    JOIN     tl.track t
    ORDER BY tl.position ASC
';

$albums = $em->createQuery($dql)->getResult();

foreach ($albums as $album) {
    echo $album->getTitle() . PHP_EOL;

    foreach ($album->getTracklist() as $track) {
        echo sprintf("\t#%d - %-20s (%s) %s\n", 
            $track->getPosition(),
            $track->getTrack()->getTitle(),
            $track->getTrack()->getDuration()->format('H:i:s'),
            $track->isPromoted() ? ' - PROMOTED!' : ''
        );
    }   
}

परिणाम वही हैं जो मैं उम्मीद कर रहा हूं, यानी: उपयुक्त क्रम में उनके ट्रैक वाले एल्बमों की सूची और पदोन्नत लोगों को प्रचारित के रूप में चिह्नित किया जा रहा है।

The Metallica Collection
    #1 - Nothing Else Matters (00:06:29) 
Master of Puppets
    #1 - Damage Inc.          (00:05:33) 
    #2 - Nothing Else Matters (00:06:29)  - PROMOTED!
    #3 - Battery              (00:05:13) 

तो क्या गलत हुआ?

यह कोड दर्शाता है कि क्या गलत है:

foreach ($album->getTracklist() as $track) {
    echo $track->getTrack()->getTitle();
}

Album::getTracklist()AlbumTrackReferenceवस्तुओं के बजाय वस्तुओं की एक सरणी देता है Track। मैं छद्म विधियों का कारण नहीं बना सकता अगर दोनों, Albumऔर विधि Trackहो तो क्या होगा getTitle()? मैं Album::getTracklist()विधि के भीतर कुछ अतिरिक्त प्रसंस्करण कर सकता हूं लेकिन ऐसा करने का सबसे सरल तरीका क्या है? क्या मैं मजबूर हूं कि मैं ऐसा कुछ लिखूं?

public function getTracklist() {
    $tracklist = array();

    foreach ($this->tracklist as $key => $trackReference) {
        $tracklist[$key] = $trackReference->getTrack();

        $tracklist[$key]->setPosition($trackReference->getPosition());
        $tracklist[$key]->setPromoted($trackReference->isPromoted());
    }

    return $tracklist;
}

// And some extra getters/setters in Track class

संपादित करें

@beberlei ने प्रॉक्सी तरीकों का उपयोग करने का सुझाव दिया:

class AlbumTrackReference {
    public function getTitle() {
        return $this->getTrack()->getTitle()
    }
}

यह एक अच्छा विचार होगा, लेकिन मैं दोनों तरफ से उस "संदर्भ वस्तु" का उपयोग कर रहा हूं: $album->getTracklist()[12]->getTitle()और $track->getAlbums()[1]->getTitle()इसलिए getTitle()विधि को आह्वान के संदर्भ के आधार पर अलग-अलग डेटा वापस करना चाहिए।

मुझे ऐसा कुछ करना होगा:

 getTracklist() {
     foreach ($this->tracklist as $trackRef) { $trackRef->setContext($this); }
 }

 // ....

 getAlbums() {
     foreach ($this->tracklist as $trackRef) { $trackRef->setContext($this); }
 }

 // ...

 AlbumTrackRef::getTitle() {
      return $this->{$this->context}->getTitle();
 }

और यह बहुत साफ तरीका नहीं है।


2
आप एल्बमट्रैक्शन को कैसे संभालते हैं? उदाहरण के लिए $ एल्बम-> addTrack () या $ एल्बम-> removeTrack ()?
डैनियल

मुझे समझ नहीं आया कि आप संदर्भ के बारे में टिप्पणी करें। मेरे विचार में डेटा संदर्भ पर निर्भर नहीं करता है। ऑब्जेक्ट के बारे में $album->getTracklist()[12]है AlbumTrackRef, इसलिए $album->getTracklist()[12]->getTitle()हमेशा ट्रैक का शीर्षक लौटाएगा (यदि आप प्रॉक्सी विधि का उपयोग कर रहे हैं)। जबकि $track->getAlbums()[1]है Albumवस्तु, इसलिए $track->getAlbums()[1]->getTitle()हमेशा एल्बम का शीर्षक वापस आ जाएगी।
विनियस फागुंडेस

एक और विचार AlbumTrackReferenceदो प्रॉक्सी तरीकों पर उपयोग कर रहा है , getTrackTitle()और getAlbumTitle
विनियस फागुंडेस

जवाबों:


158

मैंने डॉक्ट्रिन उपयोगकर्ता मेलिंग सूची में एक समान प्रश्न खोला है और वास्तव में सरल उत्तर मिला है;

एक इकाई के रूप में कई से कई संबंधों पर विचार करें, और तब आपको पता चलता है कि आपके पास 3 वस्तुएं हैं, उनके बीच एक-से-कई और कई-से-एक संबंध हैं।

http://groups.google.com/group/doctrine-user/browse_thread/thread/d1d87c96052e76f7/436b896e83c10868#436b896e83c10868

एक बार एक संबंध डेटा है, यह एक रिश्ता नहीं है!


क्या किसी को पता है कि मैं इस नई इकाई को yml स्कीमा फ़ाइल के रूप में बनाने के लिए सिद्धांत कमांड लाइन टूल कैसे प्राप्त कर सकता हूं? यह आदेश: app/console doctrine:mapping:import AppBundle ymlअभी भी मूल दो तालिकाओं के लिए कईTMMany संबंध उत्पन्न करता है और बस एक इकाई के रूप में इसे :/
छिपाने के

foreach ($album->getTracklist() as $track) { echo $track->getTrack()->getTitle(); }@Crozin द्वारा प्रदान किए गए और के बीच क्या अंतर है consider the relationship as an entity? मुझे लगता है कि वह क्या पूछना चाहता हूँ कैसे रिलेशनल इकाई छोड़ सकते हैं और द्वारा उपयोग करते हुए एक ट्रैक के शीर्षक को पुन: प्राप्त करने के लिए हैforeach ($album->getTracklist() as $track) { echo $track->getTitle(); }
पांडा

6
"एक बार जब किसी संबंध में डेटा होता है, तो यह कोई और संबंध नहीं होता है" यह वास्तव में ज्ञानवर्धक था। मैं सिर्फ एक इकाई के दृष्टिकोण से एक संबंध के बारे में नहीं सोच सकता था!
प्याज

क्या होगा अगर संबंध पहले से ही बनाया गया था और कई से कई के रूप में इस्तेमाल किया गया था। हमने महसूस किया कि हमें अपने कई क्षेत्रों में अतिरिक्त क्षेत्रों की आवश्यकता है इसलिए हमने एक अलग इकाई बनाई। मौजूदा डेटा और एक ही नाम के साथ एक मौजूदा तालिका के साथ परेशानी है, यह दोस्त बनना नहीं चाहता है। क्या किसी ने इससे पहले इसकी कोशिश करके देखी है।
टायलरिज़्म

इस तरह की सोच रखने वालों के लिए: इसकी तालिका के रूप में कई-से-कई संयुक्त (पहले से मौजूद) के साथ एक इकाई का निर्माण करना, हालांकि, कई-से-कई रखने वाली संस्थाओं को एक-से-कई के बजाय नई इकाई के लिए अनुकूलित किया जाना चाहिए। बाहरी लोगों के लिए भी इंटरफेस (पूर्व-से-कई के लिए गेटर्स / सेटर) सबसे अधिक अनुकूल होने की संभावना है।
जाकुमी १

17

$ एल्बम-> getTrackList () से आपको "AlbumTrackReference" इकाइयाँ वापस मिल जाएंगी, इसलिए ट्रैक और प्रॉक्सी के तरीकों को जोड़ने के बारे में क्या?

class AlbumTrackReference
{
    public function getTitle()
    {
        return $this->getTrack()->getTitle();
    }

    public function getDuration()
    {
        return $this->getTrack()->getDuration();
    }
}

इस तरह से आपका लूप काफी हद तक सरल हो जाता है, साथ ही साथ एल्बम के ट्रैक्स को लूप करने से संबंधित अन्य सभी कोड भी, क्योंकि सभी तरीके एल्बमट्रैक के अंदर सम्‍मिलित हैं:

foreach ($album->getTracklist() as $track) {
    echo sprintf("\t#%d - %-20s (%s) %s\n", 
        $track->getPosition(),
        $track->getTitle(),
        $track->getDuration()->format('H:i:s'),
        $track->isPromoted() ? ' - PROMOTED!' : ''
    );
}

Btw आप को एल्बमट्रैक्शन का नाम बदलना चाहिए (उदाहरण के लिए "एल्बमट्रैक")। यह स्पष्ट रूप से न केवल एक संदर्भ है, बल्कि अतिरिक्त तर्क है। चूंकि शायद ऐसे ट्रैक भी हैं जो एक एल्बम से जुड़े नहीं हैं, लेकिन सिर्फ प्रोमो-सीडी के माध्यम से उपलब्ध हैं या ऐसा कुछ है जो एक क्लीनर को भी अनुमति देता है।


1
प्रॉक्सी तरीके 100% में समस्या को हल नहीं करते हैं (मेरे संपादन की जांच करें)। Btw You should rename the AlbumT(...)- अच्छी बात
17

3
आपके पास दो तरीके क्यों नहीं हैं? getAlbumTitle () और GetTrackTitle () AlbumTrackReference ऑब्जेक्ट पर? दोनों अपने-अपने सब-सब्जेक्ट्स पर प्रॉक्सी करते हैं।
बीबरली

लक्ष्य सबसे प्राकृतिक वस्तु एपीआई है। $album->getTracklist()[1]->getTrackTitle()के रूप में अच्छा / बुरा रूप है $album->getTracklist()[1]->getTrack()->getTitle()। हालाँकि ऐसा लगता है कि मुझे दो अलग-अलग वर्ग रखने होंगे: एक एल्बम के लिए- ट्रैक संदर्भ और दूसरा ट्रैक-> एल्बम संदर्भ - और इसे लागू करना बहुत कठिन है। तो शायद यह अब तक का सबसे अच्छा समाधान है ...
क्रोज़िन

13

कुछ भी नहीं एक अच्छा उदाहरण धड़कता है

इस साइट के संबंध में अतिरिक्त विशेषताओं को संग्रहीत करने के लिए 3 प्रतिभागी वर्गों के बीच एक-से-कई / कई-से-एक संगठनों के एक स्वच्छ कोडिंग उदाहरण की तलाश में लोगों के लिए:

3 भाग लेने वाले वर्गों के बीच एक-से-कई / कई-से-एक संघों का अच्छा उदाहरण

अपनी प्राथमिक कुंजियों के बारे में सोचें

अपनी प्राथमिक कुंजी के बारे में भी सोचें। आप अक्सर इस तरह के रिश्तों के लिए मिश्रित कुंजियों का उपयोग कर सकते हैं। सिद्धांत मूल रूप से इसका समर्थन करता है। आप अपनी संदर्भित संस्थाओं को आईडी बना सकते हैं। यहां कंपोजिट कीज पर डॉक्यूमेंटेशन देखें


10

मुझे लगता है कि मैं प्रॉक्सी तरीकों का उपयोग करने के @ beberlei के सुझाव के साथ जाऊंगा। इस प्रक्रिया को सरल बनाने के लिए आप क्या कर सकते हैं दो इंटरफेस को परिभाषित करना है:

interface AlbumInterface {
    public function getAlbumTitle();
    public function getTracklist();
}

interface TrackInterface {
    public function getTrackTitle();
    public function getTrackDuration();
}

फिर, आपके Albumऔर आपके दोनों Trackउन्हें लागू कर सकते हैं, जबकि AlbumTrackReferenceअभी भी दोनों को लागू कर सकते हैं, निम्नानुसार:

class Album implements AlbumInterface {
    // implementation
}

class Track implements TrackInterface {
    // implementation
}

/** @Entity whatever */
class AlbumTrackReference implements AlbumInterface, TrackInterface
{
    public function getTrackTitle()
    {
        return $this->track->getTrackTitle();
    }

    public function getTrackDuration()
    {
        return $this->track->getTrackDuration();
    }

    public function getAlbumTitle()
    {
        return $this->album->getAlbumTitle();
    }

    public function getTrackList()
    {
        return $this->album->getTrackList();
    }
}

इस तरह, आपके तर्क है कि सीधे एक संदर्भित निकाल कर Trackया एक Album, और सिर्फ यह इतना है कि यह एक का उपयोग करता है की जगह TrackInterfaceया AlbumInterface, आप अपने उपयोग करने के लिए मिलता है AlbumTrackReferenceकिसी भी संभावित मामले में। तुम क्या जरूरत है इंटरफेस के बीच के तरीकों में थोड़ा अंतर करना है।

यह DQL और न ही रिपॉजिटरी तर्क में अंतर नहीं करेगा, लेकिन आपकी सेवाएं इस तथ्य को अनदेखा कर देंगी कि आप एक Albumया एक AlbumTrackReference, या एक Trackया एक से गुजर रहे हैं AlbumTrackReferenceक्योंकि आपने एक इंटरफ़ेस के पीछे सब कुछ छिपा दिया है :)

उम्मीद है की यह मदद करेगा!


7

सबसे पहले, मैं ज्यादातर उनके सुझावों पर बीबरेली से सहमत हूं। हालाँकि, आप अपने आप को एक जाल में डिजाइन कर सकते हैं। आपका डोमेन एक ट्रैक के लिए प्राकृतिक कुंजी होने के लिए शीर्षक पर विचार करता प्रतीत होता है, जो संभवतः आपके द्वारा आए परिदृश्य के 99% के लिए मामला है। हालांकि, क्या होगा अगर कठपुतलियों के मास्टर पर बैटरी , मेटालिका संग्रह पर संस्करण की तुलना में एक अलग संस्करण (अलग लंबाई, लाइव, ध्वनिक, रीमिक्स, रीमस्टर्ड, आदि) है ।

उस मामले को आप (या अनदेखा) कैसे संभालना चाहते हैं, इस पर निर्भर करते हुए, आप या तो बीबरली के सुझाए गए मार्ग पर जा सकते हैं, या एल्बम में अपने प्रस्तावित अतिरिक्त तर्क के साथ जा सकते हैं :: getTracklist ()। व्यक्तिगत रूप से, मुझे लगता है कि आपके एपीआई को साफ रखने के लिए अतिरिक्त तर्क उचित है, लेकिन दोनों में अपनी योग्यता है।

यदि आप मेरे उपयोग के मामले को समायोजित करना चाहते हैं, तो आप ट्रैक में अन्य ट्रैक के लिए एक स्वयं संदर्भित OneToMany शामिल कर सकते हैं, संभवतः $ इसी तरह के क्रैक। इस मामले में, ट्रैक बैटरी के लिए दो इकाइयां होंगी , एक द मेटालिका कलेक्शन के लिए और एक मास्टर ऑफ द पपेट्स के लिए । फिर प्रत्येक समान ट्रैक इकाई में एक दूसरे के लिए एक संदर्भ होगा। इसके अलावा, यह मौजूदा एल्बमट्रैक रेफरेंस वर्ग से छुटकारा पा लेगा और आपके वर्तमान "मुद्दे" को समाप्त कर देगा। मैं इस बात से सहमत हूं कि यह सिर्फ जटिलता को एक अलग बिंदु पर ले जा रहा है, लेकिन यह एक usecase को संभालने में सक्षम है जो यह पहले सक्षम नहीं था।


6

आप "सबसे अच्छा तरीका" के लिए पूछते हैं लेकिन कोई सबसे अच्छा तरीका नहीं है। कई तरीके हैं और आपने पहले से ही उनमें से कुछ की खोज की है। जब आप एसोसिएशन क्लासेस का उपयोग पूरी तरह से आप और आपके ठोस डोमेन पर करते हैं, तो आप एसोसिएशन प्रबंधन का प्रबंधन और / या कैसे एनकैप्सुलेट करना चाहते हैं, कोई भी आपको "सर्वश्रेष्ठ तरीका" नहीं दिखा सकता है जिससे मैं डरता हूं।

इसके अलावा, समीकरण से Doctrine और रिलेशनल डेटाबेस को हटाकर प्रश्न को बहुत सरल बनाया जा सकता है। आपके प्रश्न का सार सादे OOP में एसोसिएशन कक्षाओं से निपटने के तरीके के बारे में एक प्रश्न को उबालता है।


6

मैं संघ के वर्ग (अतिरिक्त कस्टम क्षेत्रों के साथ) एनोटेशन और कई-कई एनोटेशन में परिभाषित जॉइन टेबल के साथ संघर्ष से मिल रहा था।

प्रत्यक्ष-से-कई संबंधों के साथ दो संस्थाओं में मानचित्रण परिभाषाओं में 'जॉइनटेबल' एनोटेशन का उपयोग करके ज्वाइन टेबल के स्वचालित निर्माण में परिणाम दिखाई दिया। हालाँकि, जॉइनिंग टेबल को पहले से ही इसकी अंतर्निहित इकाई वर्ग में एक एनोटेशन द्वारा परिभाषित किया गया था और मैं चाहता था कि यह एसोसिएशन एंटिटी क्लास की अपनी फील्ड परिभाषाओं का उपयोग करे ताकि अतिरिक्त कस्टम फ़ील्ड्स के साथ ज्वाइन टेबल का विस्तार किया जा सके।

स्पष्टीकरण और समाधान है कि ऊपर FMaz008 द्वारा की पहचान की। मेरी स्थिति में, यह ' फोरम एनोटेशन सवाल ' फोरम में इस पोस्ट के लिए धन्यवाद था । यह पोस्ट कई टोमनी यूनी-दिशात्मक संबंधों के बारे में सिद्धांत सिद्धांत पर ध्यान आकर्षित करती है । 'एसोसिएशन एंटिटी क्लास' का उपयोग करने के दृष्टिकोण के बारे में नोट को देखें। -ऑपरेटिव एंटिटी क्लास में एनोटेशन। इस मंच पोस्ट एसोसिएशन मॉडल में अतिरिक्त क्षेत्रों के साथ एक उदाहरण दिया गया है :

public class Person {

  /** @OneToMany(targetEntity="AssignedItems", mappedBy="person") */
  private $assignedItems;

}

public class Items {

    /** @OneToMany(targetEntity="AssignedItems", mappedBy="item") */
    private $assignedPeople;
}

public class AssignedItems {

    /** @ManyToOne(targetEntity="Person")
    * @JoinColumn(name="person_id", referencedColumnName="id")
    */
private $person;

    /** @ManyToOne(targetEntity="Item")
    * @JoinColumn(name="item_id", referencedColumnName="id")
    */
private $item;

}

3

यह वास्तव में उपयोगी उदाहरण है। यह दस्तावेज़ीकरण सिद्धांत 2 में कमी है।

आपको बहुत धन्यवाद।

समीपवर्ती कार्यों के लिए किया जा सकता है:

class AlbumTrack extends AlbumTrackAbstract {
   ... proxy method.
   function getTitle() {} 
}

class TrackAlbum extends AlbumTrackAbstract {
   ... proxy method.
   function getTitle() {}
}

class AlbumTrackAbstract {
   private $id;
   ....
}

तथा

/** @OneToMany(targetEntity="TrackAlbum", mappedBy="album") */
protected $tracklist;

/** @OneToMany(targetEntity="AlbumTrack", mappedBy="track") */
protected $albumsFeaturingThisTrack;

3

क्या आप मेटाडेटा का उल्लेख कर रहे हैं, डेटा के बारे में डेटा। मेरे पास इस परियोजना के लिए यही मुद्दा था जिस पर मैं वर्तमान में काम कर रहा हूं और इसे जानने के लिए कुछ समय बिताना पड़ा। यहां पोस्ट करने के लिए बहुत अधिक जानकारी है, लेकिन नीचे दो लिंक हैं जो आपको उपयोगी लग सकते हैं। वे सिम्फनी ढांचे का संदर्भ देते हैं, लेकिन सिद्धांत ओआरएम पर आधारित हैं।

http://melikedev.com/2010/04/06/symfony-saving-metadata-during-form-save-sort-ids/

http://melikedev.com/2009/12/09/symfony-w-doctrine-saving-many-to-many-mm-relationships/

गुड लक, और अच्छा मेटालिका संदर्भ!


3

इसका समाधान डॉक्ट्रिन के दस्तावेज में है। एफएक्यू में आप इसे देख सकते हैं:

http://docs.doctrine-project.org/en/2.1/reference/faq.html#how-can-i-add-columns-to-a-many-to-many-table

और ट्यूटोरियल यहाँ है:

http://docs.doctrine-project.org/en/2.1/tutorials/composite-primary-keys.html

तो आप अब और नहीं करते हैं, manyToManyलेकिन आपको एक अतिरिक्त एंटिटी बनानी होगी और manyToOneअपनी दो संस्थाओं को लगाना होगा।

@ F00bar टिप्पणी के लिए ADD :

यह सरल है, आपको बस कुछ ऐसा करना है:

Article  1--N  ArticleTag  N--1  Tag

तो आप एक ArticleTag नामक संस्था बनाएं

ArticleTag:
  type: entity
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  manyToOne:
    article:
      targetEntity: Article
      inversedBy: articleTags
  fields: 
    # your extra fields here
  manyToOne:
    tag:
      targetEntity: Tag
      inversedBy: articleTags

मुझे उम्मीद है यह मदद करेगा



यह है कि मैं क्या देख रहा था, धन्यवाद! दुर्भाग्य से, तीसरे उपयोग के मामले में कोई yml उदाहरण नहीं है! :(क्या कोई तीसरे उपयोग के मामले का एक पूर्णांक yml प्रारूप का उपयोग कर साझा कर सकता है? मैं वास्तव में आशान्वित रहूंगा:#
स्टेफेन

मैंने आपके मामले के जवाब में जोड़ा है;)
मिर्ज़ा सेलिमोविच

यह गलत है। इकाई को आईडी (आईडी) ऑटो के साथ नहीं होना चाहिए। यह गलत है, मैं सही उदाहरण बनाने की कोशिश कर रहा हूं
गैटुनॉक्स

अगर सही तरीके से फॉर्मेट किया जाए तो मैं एक नया उत्तर दूंगा
गतुनॉक्स

3

दिशाहीन। बस इनडायरेक्ट करें: (विदेशी कॉलम का नाम) इसे द्विदिश बनाने के लिए।

# config/yaml/ProductStore.dcm.yml
ProductStore:
  type: entity
  id:
    product:
      associationKey: true
    store:
      associationKey: true
  fields:
    status:
      type: integer(1)
    createdAt:
      type: datetime
    updatedAt:
      type: datetime
  manyToOne:
    product:
      targetEntity: Product
      joinColumn:
        name: product_id
        referencedColumnName: id
    store:
      targetEntity: Store
      joinColumn:
        name: store_id
        referencedColumnName: id

मुझे उम्मीद है यह मदद करेगा। फिर मिलते हैं।


2

आप प्राप्त कर सकते हैं कि आप क्लास टेबल इनहेरिटेंस के साथ क्या चाहते हैं जहाँ आप एल्बमट्रैक को एल्बमट्रैक में बदलें:

class AlbumTrack extends Track { /* ... */ }

और getTrackList()इसमें ऐसी AlbumTrackवस्तुएँ शामिल होंगी जिन्हें आप तब उपयोग कर सकते हैं जैसे आप चाहते हैं:

foreach($album->getTrackList() as $albumTrack)
{
    echo sprintf("\t#%d - %-20s (%s) %s\n", 
        $albumTrack->getPosition(),
        $albumTrack->getTitle(),
        $albumTrack->getDuration()->format('H:i:s'),
        $albumTrack->isPromoted() ? ' - PROMOTED!' : ''
    );
}

आपको यह सुनिश्चित करने के लिए कि आपको प्रदर्शन-वार का नुकसान न हो, इसकी जांच करने की आवश्यकता होगी।

आपका वर्तमान सेट-अप सरल, कुशल और समझने में आसान है, भले ही कुछ शब्दार्थ आपके साथ सही से न बैठते हों।


0

एल्बम वर्ग के अंदर सभी एल्बम ट्रैक बनाते समय, आप एक और रिकॉर्ड के लिए एक और क्वेरी उत्पन्न करेंगे। यह प्रॉक्सी पद्धति के कारण है। मेरे कोड का एक और उदाहरण है (विषय में अंतिम पोस्ट देखें): http://groups.google.com/group/doctrine-user/browse_thread/thread/d1d87c96052e76f7/436b894e83c10868#436b896e83c10868

क्या इसका समाधान करने की कोई अन्य विधि है? क्या कोई एक बेहतर समाधान में शामिल नहीं है?


1
जब भी यह सैद्धांतिक रूप से प्रश्न का उत्तर दे सकता है, तो उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर होगा
स्पॉन्टिफिक्सस

0

यहाँ Doctrine2 प्रलेखन में वर्णित समाधान है

<?php
use Doctrine\Common\Collections\ArrayCollection;

/** @Entity */
class Order
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @ManyToOne(targetEntity="Customer") */
    private $customer;
    /** @OneToMany(targetEntity="OrderItem", mappedBy="order") */
    private $items;

    /** @Column(type="boolean") */
    private $payed = false;
    /** @Column(type="boolean") */
    private $shipped = false;
    /** @Column(type="datetime") */
    private $created;

    public function __construct(Customer $customer)
    {
        $this->customer = $customer;
        $this->items = new ArrayCollection();
        $this->created = new \DateTime("now");
    }
}

/** @Entity */
class Product
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @Column(type="string") */
    private $name;

    /** @Column(type="decimal") */
    private $currentPrice;

    public function getCurrentPrice()
    {
        return $this->currentPrice;
    }
}

/** @Entity */
class OrderItem
{
    /** @Id @ManyToOne(targetEntity="Order") */
    private $order;

    /** @Id @ManyToOne(targetEntity="Product") */
    private $product;

    /** @Column(type="integer") */
    private $amount = 1;

    /** @Column(type="decimal") */
    private $offeredPrice;

    public function __construct(Order $order, Product $product, $amount = 1)
    {
        $this->order = $order;
        $this->product = $product;
        $this->offeredPrice = $product->getCurrentPrice();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.