ডক্ট্রাইন 2: রেফারেন্স সারণীতে অতিরিক্ত কলাম সহ বহু থেকে বহুকে পরিচালনা করার সর্বোত্তম উপায়


282

আমি ভাবছি যে ডক্ট্রাইন 2-তে বহু-থেকে-বহু সম্পর্কের সাথে কাজ করার সবচেয়ে ভাল, সবচেয়ে পরিষ্কার এবং সবচেয়ে সহজ উপায়।

আসুন ধরে নেওয়া যাক যে আমরা বেশ কয়েকটি ট্র্যাক সহ মেটালিকার বাইরের মাস্টার অফ পুতুলের মতো একটি অ্যালবাম পেয়েছি । তবে দয়া করে এই বিষয়টি লক্ষ্য করুন যে ব্যাটারি বাই মেটালিকার মতো আরও একটি অ্যালবামে একটি ট্র্যাক উপস্থিত হতে পারে - তিনটি অ্যালবাম এই ট্র্যাকটির বৈশিষ্ট্যযুক্ত।

সুতরাং আমার যা দরকার তা হল অতিরিক্ত অতিরিক্ত কলাম (নির্দিষ্ট অ্যালবামে ট্র্যাকের অবস্থানের মতো) সহ তৃতীয় টেবিল ব্যবহার করে অ্যালবাম এবং ট্র্যাকগুলির মধ্যে বহু থেকে বহু সম্পর্ক। প্রকৃতপক্ষে আমাকে ব্যবহার করতে হবে, যেমন ডক্ট্রিনের ডকুমেন্টেশনগুলি পরামর্শ দেয়, সেই কার্যকারিতা অর্জনের জন্য দ্বিগুণ একের সাথে অনেকের সম্পর্ক।

/** @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
আপনি কীভাবে অ্যালবাম ট্র্যাকরাইফারেন্স পরিচালনা করবেন? উদাহরণের জন্য $ অ্যালবাম-> অ্যাডট্র্যাক () বা $ অ্যালবাম-> সরান ট্র্যাক ()?
ড্যানিয়েল

আমি প্রসঙ্গে আপনি মন্তব্য বুঝতে পারি না। আমার মতামত ডেটা প্রসঙ্গে নির্ভর করে না। আমাদের সম্পর্কে $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এখনও মূল দুটি টেবিলের সাথে অনেকগুলি সম্পর্ক তৈরি করে এবং তৃতীয় সারণিকে সত্তা হিসাবে বিবেচনা করার পরিবর্তে তা উপেক্ষা করুন:/
স্টাফেন

foreach ($album->getTracklist() as $track) { echo $track->getTrack()->getTitle(); }@ ক্রোজিন এবং প্রদানের মধ্যে আলাদা কী consider the relationship as an entity? আমার মনে হয় তিনি কী জিজ্ঞাসা করতে চান তা কীভাবে সম্পর্কিত সত্তাকে এড়িয়ে যাওয়া এবং ট্র্যাকের শিরোনাম পুনরুদ্ধার করে ব্যবহার করতে পারেনforeach ($album->getTracklist() as $track) { echo $track->getTitle(); }
পান্ডা

6
"একবার কোনও সম্পর্কের ডেটা হয়ে গেলে এটি আর কোনও সম্পর্ক হয় না" এটি সত্যই আলোকিত ছিল। আমি সত্তার দৃষ্টিকোণ থেকে একটি সম্পর্ক সম্পর্কে ভাবতে পারি না!
পেঁয়াজ

সম্পর্কটি ইতিমধ্যে অনেকের কাছে তৈরি হয়ে এবং ব্যবহার করা থাকলে কী হবে। আমরা বুঝতে পারি যে আমাদের অনেকের কাছে আমাদের অতিরিক্ত ক্ষেত্রের প্রয়োজন তাই আমরা একটি আলাদা সত্ত্বা তৈরি করেছি। সমস্যাটি হ'ল বিদ্যমান ডেটা এবং একই নামের একটি বিদ্যমান টেবিল সহ, এটি বন্ধু হতে চায় বলে মনে হয় না। কেউ কি এটা আগে ব্যবহার করেছেন?
টাইলারিজম

যারা ভাবছেন তাদের জন্য: এটির সারণীটি কাজ করে (ইতিমধ্যে বিদ্যমান) বহু-বহু-সংযুক্ত হয়ে একটি সত্তা তৈরি করা যায়, তবে, বহু-বহু-সংখ্যক সংস্থাগুলি একের সাথে একাধিককে নতুন সত্তায় অভিযোজিত করতে হবে। বাইরের ইন্টারফেসগুলিও (প্রাক্তন বহু-অনেকের জন্য গেটার / সেটটার) সম্ভবত অভিযোজিত হতে হয়।
জাকুমি

17

$ অ্যালবাম-> getTrackList () থেকে আপনি আবার "অ্যালবাম ট্র্যাকরফারেন্স" সত্ত্বা ফিরে পাবেন, তাহলে ট্র্যাক এবং প্রক্সি থেকে পদ্ধতি যুক্ত করার কী আছে?

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!' : ''
    );
}

বিটিডব্লিউ আপনার অ্যালবাম ট্র্যাকরাইফারেন্সের নামকরণ করা উচিত (উদাহরণস্বরূপ "অ্যালবাম ট্র্যাক")। এটি স্পষ্টভাবে কেবল একটি রেফারেন্সই নয়, এতে অতিরিক্ত যুক্তিও রয়েছে। যেহেতু সম্ভবত এমন ট্র্যাকগুলিও রয়েছে যা কোনও অ্যালবামের সাথে সংযুক্ত নয় তবে কেবল একটি প্রোমো সিডির মাধ্যমে পাওয়া যায় বা এটি এমন কোনও ক্লিনারকে পৃথক করারও অনুমতি দেয়।


1
প্রক্সি পদ্ধতিগুলি 100% এ সমস্যার সমাধান করে না (আমার সম্পাদনা পরীক্ষা করুন)। Btw You should rename the AlbumT(...)- ভাল কথা
ক্রোজিন

3
আপনার দুটি পদ্ধতি আছে কেন? অ্যালবামটিটেল () এবং getTrackTitle () অ্যালবামট্র্যাকআরফেসেন্স অবজেক্টে পাবেন? উভয় তাদের নিজ নিজ subobjects প্রক্সি।
বেবারলি

লক্ষ্যটি হ'ল সর্বাধিক প্রাকৃতিক অবজেক্ট এপিআই। $album->getTracklist()[1]->getTrackTitle()হিসাবে ভাল / খারাপ $album->getTracklist()[1]->getTrack()->getTitle()। তবে মনে হচ্ছে আমার দুটি পৃথক শ্রেণি থাকতে হবে: একটি অ্যালবাম-> ট্র্যাক রেফারেন্সের জন্য এবং অন্যটি ট্র্যাক-> অ্যালবামের রেফারেন্সের জন্য - এবং এটি কার্যকর করা খুব কঠিন। তাই সম্ভবত এটি এখন পর্যন্ত সেরা সমাধান ...
ক্রোজিন

13

কিছুই ভাল উদাহরণ বীট

সম্পর্কের ক্ষেত্রে অতিরিক্ত গুণাবলী সংরক্ষণ করার জন্য 3 অংশগ্রহনকারী শ্রেণীর মধ্যে এক থেকে বহু / বহু-এক-সহযোগী সংস্থার একটি পরিষ্কার কোডিং উদাহরণ সন্ধানকারী ব্যক্তিদের জন্য এই সাইটটি দেখুন:

3 অংশগ্রহনকারী ক্লাসের মধ্যে এক থেকে বহু / অনেকগুলি এক সংঘের দুর্দান্ত উদাহরণ

আপনার প্রাথমিক কীগুলি সম্পর্কে চিন্তা করুন

আপনার প্রাথমিক কী সম্পর্কেও ভাবুন। আপনি এই জাতীয় সম্পর্কের জন্য প্রায়শই সম্মিলিত কীগুলি ব্যবহার করতে পারেন। মতবাদ দেশীয়ভাবে এটিকে সমর্থন করে। আপনি আপনার রেফারেন্স সত্তাকে আইডিতে পরিণত করতে পারেন। যৌগিক কীগুলিতে ডকুমেন্টেশনটি এখানে পরীক্ষা করুন


10

আমি মনে করি আমি @ বেরবেরির প্রক্সি পদ্ধতি ব্যবহারের পরামর্শ নিয়ে যাব। এই প্রক্রিয়াটিকে সহজতর করতে আপনি যা করতে পারেন তা হ'ল দুটি ইন্টারফেসকে সংজ্ঞায়িত করা:

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কোন সম্ভাব্য ক্ষেত্রে। আপনার যা প্রয়োজন তা হ'ল ইন্টারফেসগুলির মধ্যে কিছুটা পদ্ধতি পার্থক্য করা।

এটি ডিকিউএল বা রেপোজিটরি যুক্তিকে আলাদা করবে না, তবে আপনার পরিষেবাগুলি কেবল এই সত্যটিকে এড়িয়ে যাবে যে আপনি কোনও Albumবা একটি AlbumTrackReference, বা একটি Trackবা একটি পাশ করছেন AlbumTrackReferenceকারণ আপনি একটি ইন্টারফেসের পিছনে সমস্ত কিছু লুকিয়ে রেখেছেন :)

আশাকরি এটা সাহায্য করবে!


7

প্রথমত, আমি বেশিরভাগই তার পরামর্শগুলিতে বেবারলেই একমত হই। তবে আপনি নিজেকে ফাঁদে ফেলতে পারেন into আপনার ডোমেন শিরোনামটিকে একটি ট্র্যাকের প্রাকৃতিক কী হিসাবে বিবেচনা করছে বলে মনে হচ্ছে, যা সম্ভবত আপনি 99% পরিস্থিতিতে এসে পৌঁছেছেন। যাইহোক, যদি ব্যাটারি উপর পুতুল মাস্টার কোনো ভিন্ন সংস্করণ (বিভিন্ন দৈর্ঘ্য, বাস, শাব্দ, রিমিক্স, রেমাস্তের্দ, ইত্যাদি) সংস্করণটি চেয়ে মেটালিকা সংগ্রহ

আপনি কীভাবে হ্যান্ডেল করতে চান (বা উপেক্ষা) তার উপর নির্ভর করে আপনি হয় বেরবেরির প্রস্তাবিত পথে যেতে পারেন, বা কেবল অ্যালবামে আপনার প্রস্তাবিত অতিরিক্ত যুক্তি দিয়ে যেতে পারেন :: getTracklist ()। ব্যক্তিগতভাবে, আমি মনে করি অতিরিক্ত যুক্তি আপনার এপিআই পরিষ্কার রাখতে ন্যায়সঙ্গত, তবে উভয়েরই যোগ্যতা রয়েছে।

আপনি যদি আমার ব্যবহারের ক্ষেত্রে সামঞ্জস্য করতে চান তবে আপনার নিজের ট্র্যাকগুলিতে অন্য ট্র্যাকগুলিতে স্বতঃসূচক ওয়ানটোম্যানির সমন্বয় থাকতে পারে, সম্ভবত $ অনুরূপ ট্র্যাক। এই ক্ষেত্রে, ট্র্যাক ব্যাটারির জন্য দুটি সত্ত্বা থাকবে , একটি দি মেটালিকা সংগ্রহের জন্য এবং একটি পুতুলের পুতুলের জন্য । তারপরে প্রতিটি অনুরূপ ট্র্যাক সত্তা একে অপরের সাথে একটি উল্লেখ থাকতে পারে। এছাড়াও, এটি বর্তমান অ্যালবাম ট্র্যাকরফারেন্স ক্লাস থেকে মুক্তি পাবে এবং আপনার বর্তমান "সমস্যা" মুছে ফেলবে। আমি একমত যে এটি জটিলতাটি কেবল একটি ভিন্ন বিন্দুতে নিয়ে যাচ্ছে, তবে এটি এমন ইউসকেস পরিচালনা করতে সক্ষম যা এটি আগে সক্ষম ছিল না।


6

আপনি "সেরা উপায়" চেয়েছেন তবে এর থেকে সেরা উপায় নেই। অনেকগুলি উপায় রয়েছে এবং আপনি ইতিমধ্যে সেগুলির কয়েকটি আবিষ্কার করেছেন। অ্যাসোসিয়েশন ক্লাসগুলি ব্যবহার করার সময় আপনি কীভাবে অ্যাসোসিয়েশন ম্যানেজমেন্ট পরিচালনা করতে এবং / অথবা এনক্যাপসুলেট করতে চান তা সম্পূর্ণভাবে আপনার এবং আপনার কংক্রিট ডোমেনের উপর নির্ভর করে, কোনও ব্যক্তি আপনাকে "সর্বোত্তম উপায়" দেখাতে পারে না বলে আমি ভীত।

তা ছাড়া, সমীকরণ থেকে ডক্ট্রিন এবং রিলেশনাল ডাটাবেসগুলি সরিয়ে প্রশ্নটি অনেক সহজ করা যেতে পারে। আপনার প্রশ্নের সারমর্মটি কীভাবে সমতল ওওপিতে অ্যাসোসিয়েশন ক্লাসগুলির সাথে ডিল করবেন সে সম্পর্কে একটি প্রশ্নে উত্সাহিত হয়।


6

আমি অ্যাসোসিয়েশন ক্লাসে সংযুক্ত টেবিলের সংঘর্ষ (অতিরিক্ত কাস্টম ক্ষেত্রগুলি সহ) টিকা এবং বহু-টু-বহু টিকাতে সংজ্ঞায়িত একটি টেবিলের সাথে সংঘাত পেয়েছিলাম।

সরাসরি বহু-থেকে-বহু সম্পর্কের সাথে দুটি সত্তায় ম্যাপিং সংজ্ঞাগুলি 'joinTable' টিকাটি ব্যবহার করে যোগদানের টেবিলটি স্বয়ংক্রিয়ভাবে তৈরির ফলাফল হিসাবে উপস্থিত হয়েছিল। তবে যোগদানের টেবিলটি ইতিমধ্যে তার অন্তর্নিহিত সত্তা শ্রেণিতে একটি টীকা দ্বারা সংজ্ঞায়িত করা হয়েছিল এবং আমি চেয়েছিলাম যে এটি এই সংস্থা সত্তা শ্রেণীর নিজস্ব ক্ষেত্রের সংজ্ঞাগুলি ব্যবহার করুন যাতে অতিরিক্ত কাস্টম ক্ষেত্রগুলির সাথে যোগদানের টেবিলটি প্রসারিত করা যায়।

ব্যাখ্যা এবং সমাধানটি উপরের FMaz008 দ্বারা চিহ্নিত করা হয়েছে। আমার পরিস্থিতিতে, এটি ' ডক্ট্রাইন টিকাশ প্রশ্ন ' ফোরামে এই পোস্টটির জন্য ধন্যবাদ ছিল । এই পোস্টটি ম্যান্টিটোম্যান ইউনি-দিকনির্দেশক সম্পর্ক সম্পর্কিত মতবাদ সংক্রান্ত ডকুমেন্টেশনের প্রতি দৃষ্টি আকর্ষণ করেছে । 'অ্যাসোসিয়েশন সত্তা শ্রেণি' ব্যবহারের পদ্ধতির সাথে সম্পর্কিত নোটটি দেখুন যার ফলে মূল সত্তা শ্রেণিতে এক থেকে এক টীকা এবং দুটি 'বহু-টু'র সাথে দুটি প্রধান সত্তা শ্রেণীর মধ্যে সরাসরি বহু থেকে বহু টীকা ম্যাপিং প্রতিস্থাপন করা হয় association -সোসিয়েটিভ সত্তা শ্রেণিতে একটি 'টিকা। অতিরিক্ত ক্ষেত্র সহ এই ফোরাম পোস্ট অ্যাসোসিয়েশন মডেলগুলিতে একটি উদাহরণ সরবরাহ করা আছে :

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

সমাধানটি ডক্ট্রিনের ডকুমেন্টেশনে রয়েছে। FAQ এ আপনি এটি দেখতে পারেন:

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 মন্তব্যের জন্য যোগ করুন:

এটি সহজ, আপনার এই জাতীয় কিছু করতে হবে:

Article  1--N  ArticleTag  N--1  Tag

সুতরাং আপনি একটি সত্তা আর্টিকেল ট্যাগ তৈরি করুন

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

আমি আসা করি এটা সাহায্য করবে


1

এটাই খুব সুন্দরভাবে আমি যা খুঁজছিলাম, ধন্যবাদ! দুর্ভাগ্যক্রমে, তৃতীয় ব্যবহারের ক্ষেত্রে কোনও 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!' : ''
    );
}

আপনি পারফরম্যান্স-ভিত্তিতে ক্ষতিগ্রস্থ না হন তা নিশ্চিত করার জন্য আপনাকে এটিকে পর্যবেক্ষণ করতে হবে need

আপনার বর্তমান সেটআপটি সহজ, দক্ষ এবং সহজে বোঝা যায় যদিও কিছু শব্দার্থবিজ্ঞান আপনার সাথে ঠিকভাবে বসে না।


0

সমস্ত অ্যালবাম ট্র্যাকগুলি অ্যালবাম শ্রেণীর ভিতরে ফর্ম করার সময়, আপনি আরও একটি রেকর্ডের জন্য আরও একটি ক্যোয়ারী তৈরি করবেন। এটি প্রক্সি পদ্ধতির কারণে। আমার কোডের আরও একটি উদাহরণ রয়েছে (বিষয়টিতে শেষ পোস্টটি দেখুন): http://groups.google.com/group/doctrine-user/browse_thread/thread/d1d87c96052e76f7/436b896e83c10868#436b896e83c10868

এর সমাধানের জন্য কি আর কোন পদ্ধতি আছে? একটি একক কি আরও ভাল সমাধানে যোগ দিতে পারে না?


1
যতক্ষণ এই তাত্ত্বিক প্রশ্নের উত্তর হতে পারে, এটা বাঞ্ছনীয় হবে উত্তর অপরিহার্য অংশের এখানে অন্তর্ভুক্ত করা, এবং রেফারেন্স এর জন্য লিঙ্ক প্রদান।
স্পনটিক্সাস

0

ডক্ট্রাইন 2 ডকুমেন্টেশনে বর্ণিত সমাধানটি এখানে রয়েছে

<?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();
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.