我正在编写一个功能,要求我的连接表的记录带有额外的元数据( 使用元数据加入表 )。我试图按照this section of the Doctrine documentation实现这一点。
请参阅下面的示例实体定义。
现在的挑战是getGroups
和setGroups
不会产生/设置Group
个实体(从Group
实例的角度来看也是如此),但是收益GroupUser
个实体。
这给管理这种关系的过程增加了很大的延迟,到目前为止这种关系非常顺利 - 例如,我不能简单地添加,删除或检查Group
是否存在于集合getGroups
{1}}收益率。
任何人都可以识别我的实现中的任何错误,或者建议采用更流畅的方式来实现这个概念吗?
提前感谢任何输入。
修改
我主要担心的是:使用此实现,从Group实体中检索用户集合需要此Entity方法的中介:
public function getUsers() {
return $this->users->map(function($groupUser){
return $groupUser->getUser();
});
}
我担心这可能意味着一场重大的表演。我不对吗?
此外,如何重新实现setUsers
方法?
群组实体:
<?php
/**
* @Entity
* @Table(name="group")
*/
class Group {
/**
* @Column(type="integer", nullable=false)
* @Id
*/
protected $id = null;
/**
* @OneToMany(targetEntity="GroupUser", mappedBy="group")
* @var \Doctrine\Common\Collections\Collection
*/
protected $users;
}
用户实体:
<?php
/**
* @Entity
* @Table(name="user")
*/
class User {
/**
* @Column(type="integer", nullable=false)
* @Id
*/
protected $id = null;
/**
* @OneToMany(targetEntity="GroupUser", mappedBy="user")
* @var \Doctrine\Common\Collections\Collection
*/
protected $groups;
}
加入实体:
<?php
/**
* @Entity
* @Table(name="group_user")
*/
class GroupUser {
/**
* @Id
* @ManyToOne(targetEntity="User", inversedBy="groups")
* @JoinColumn(name="userId", referencedColumnName="id")
*/
protected $user;
/**
* @Id
* @ManyToOne(targetEntity="Group", inversedBy="users")
* @JoinColumn(name="groupId", referencedColumnName="id")
*/
protected $group;
/**
* @Column(type="integer")
*/
protected $relationship;
}
相关 -
答案 0 :(得分:0)
我发现这个特定类型的关系的实体定义只有两个例子(见问题),但没有关于如何使用它们的示例代码。因此,相当不清楚所得到的制定者和其他人的流动性(或其他方式)。预计会有吸气剂。希望这段代码能帮助其他人做出类似尝试的方法。
在这种情况下的理想解决方案(感谢#doctrine @ freenode)是为了实现一个自定义存储库 - 一个更灵活的存储库。创造和发展的有效场所管理协会。
具有元数据类的连接表的示例自定义存储库 - 解决方案伴随原始问题中的代码
<?php
use Doctrine\ORM\EntityRepository;
class GroupUserRepository extends EntityRepository {
/**
* @param \User $user
* @param \Group $group
* @param integer $type One of the integer class constants defined by GroupUser
* @param string $role Optional string defining user's role in the group.
* @return \GroupUser
*/
public function addUserToGroup(User $user, Group $group, $relationship, $role = '') {
$groupUser = $this->findOneBy(array('user' => $user->getId(), 'group' => $group->getId()));
if(!$groupUser) {
$groupUser = new GroupUser();
$groupUser->setGroup($group);
$groupUser->setUser($user);
$groupUser->setRole($role);
$groupUser->setRelationship($relationship);
$this->_em->persist($groupUser);
}
return $groupUser;
}
/**
* @param \User $user
* @param \Group $group
* @return null
*/
public function removeUserFromGroup(User $user, Group $group) {
$groupUser = $this->findOneBy(array('user' => $user->getId(), 'group' => $group->getId()));
if($groupUser)
$this->_em->remove($groupUser);
}
}
然后,从join-table类中,将实体元数据accordingly修改为指定自定义存储库。
<?php
/**
* @Entity(repositoryClass="\Path\To\GroupUserRepository")
*/
class GroupUser {
// ...
}
这会导致自定义存储库代替默认存储库,从而使实体类的代理方法变得简单。
<?php
/**
* @Entity
*/
class Group {
/**
* @param \User $user
* @param integer $relationship One of the integer class constants defined by GroupUser
* @param string $role Optional string defining user's role in the group.
* @return \GroupUser
*/
public function addUser(User $user, $relationship, $role = '') {
return $this->_em->getRepository('GroupUser')
->addUserToGroup($user, $this, $relationship, $role);
}
}
事情和以前一样可管理。