猿问

Doctrine 2:在引用表中使用额外列处理多到多列的最佳方法

Doctrine 2:在引用表中使用额外列处理多到多列的最佳方法

我想知道什么是最好的,最干净的,最简单的方式来处理多到多的关系在原则2。

假设我们有一张专辑木偶大师金属有几个脚印。但请注意,一首歌可能会出现在更多的专辑中,比如电池金属有三张专辑都是以这首歌为特色的。

所以我需要的是专辑和曲目之间的多对多的关系,使用第三个表和一些额外的列(比如在指定相册中的曲目位置)。实际上,正如Doctrine的文档所建议的那样,我必须使用一对多的双重关系来实现这一功能。

/** @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;
    }}
慕娘9325324
浏览 469回答 3
3回答

收到一只叮咚

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();  }这不是一种非常干净的方式。

慕姐8265434

从$相册->getTrackList()中,您将获得“Al猝发TrackReference”实体返回,那么从Track和Proxy添加方法怎么样?class AlbumTrackReference{     public function getTitle()     {         return $this->getTrack()->getTitle();     }     public function getDuration()     {         return $this->getTrack()->getDuration();     }}这样,您的循环以及与循环专辑轨道相关的所有其他代码都大大简化了,因为所有方法都只是在AlbunTrakcReference中进行代理: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!' : ''     );}顺便说一句,你应该重命名“白蛋白轨迹参考”(例如,“白蛋白轨迹”)。显然,它不仅是一种引用,而且还包含额外的逻辑。因为有可能也有轨道,不是连接到一个专辑,但只有通过一个宣传CD或其他什么,这也允许一个更干净的分离。
随时随地看视频慕课网APP
我要回答