我想知道在Doctrine2中处理多对多关系的最佳,最简洁和最简单的方法是什么。
因此,我需要的是专辑和曲目之间的多对多关系,使用带有附加列的第三张表(例如曲目在指定专辑中的位置)。实际上,正如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;
}
}
样本数据:
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();
}
那不是一个很干净的方法。
我已经在“ Doctrine用户”邮件列表中打开了一个类似的问题,并且得到了一个非常简单的答案。
将多对多关系视为一个实体本身,然后您意识到您有3个对象,它们之间以一对多和多对一关系链接。
关系一旦有了数据,就不再是关系!
您好,我有多对多映射,在联接表中有额外的列。表结构如下所示。 关系如下 链接 我创建了如下POJO类 Vendor.java 学生。爪哇 测试。爪哇 供应商est.java 供应商学生测试PK。爪哇 Hibernate映射文件,如下所示 vendor.hbm.xml vendor\u student\u测试。hbm。xml 大学生hbm。xml 测验hbm。xml 我刚开始Hibernate,这是
问题内容: 当您在Android应用中处理Firebase数据(读,写…)时,您需要获取Firebase引用才能进行数据处理。 由于Firebase引用是一棵JSON树,因此,如果您指向树的根,则可以随时访问子级,而无论深度如何。 问题:从内存和延迟角度来看,在代码中处理此引用的最佳方法是什么? 根 C1 C10 C11 C2 C21 1 /在应用程序的根目录中创建静态Firebase引用。 2
我想使用XML映射在Hibernate中映射多对多的关系。 我有两个类,和。我想创建一个链接表女巫将包含复合键和3个额外的列
问题内容: 我经常遇到以下情况,其中我需要提供许多不同类型的权限。我主要在SQL Server 2000中使用ASP.NET/VB.NET。 设想 我想提供一个可以在不同参数上工作的动态权限系统。假设我想授予部门或特定人员访问应用程序的权限。并假装我们拥有不断增长的应用程序。 过去,我选择了我知道的以下两种方法之一。 将单个许可权表与特殊列一起使用,这些特殊列用于确定如何应用参数。此示例中的特殊列
问题内容: 我有一个风俗习惯。此行中的每一行都有一个图标和一些文本。这些图标在后台下载,缓存并使用回调(分别替换为)进行下载。每次getView()运行都会触发从缓存或下载中获取缩略图的逻辑。 现在,根据Romain Guy所说: “绝对不能保证的调用顺序和次数。 我已经看到这种情况的发生,因为大小为2的一行getView()被调用了6次! 如何更改代码以避免重复的缩略图获取请求并处理视图回收?
问题内容: 我正在尝试在SQL Server 11.00.3393中的查询中连接多个列。 我尝试了新功能,但是当我使用两个以上的列时,它不起作用。 所以我想知道这是否是解决问题的最佳方法: 由于价值我不能使用。 编辑 如果我尝试我会得到一个错误 CONCAT函数需要2个参数 问题答案: 通过讨论,很明显,问题出在使用VS2010编写查询,因为它使用了受限于2个参数的规范函数。可能有一种方法可以更改