我正在编写一个功能,该功能要求联接表的记录携带额外的元数据(使用元数据联接表)。我试图根据条令文件的这一部分来实现这一点。
请参阅下面的实体定义示例
现在的挑战是getGroups
和setGroups
不产生/设置Group
实体(从Group
实例的角度来看也是如此),但它们产生GroupUser
实体。
这给管理这种关系的过程增加了很大的延迟,到目前为止,这种关系非常顺利——例如,我不能简单地向getGroups
产生的集合添加、删除或检查Group
的存在。
有人能识别我的实现中的任何错误吗,或者建议一种更灵活的方式来实现这个概念吗?
提前感谢您的任何意见。
编辑:
我主要关心的是:使用此实现,从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 DoctrineCommonCollectionsCollection
*/
protected $users;
}
用户实体:
<?php
/**
* @Entity
* @Table(name="user")
*/
class User {
/**
* @Column(type="integer", nullable=false)
* @Id
*/
protected $id = null;
/**
* @OneToMany(targetEntity="GroupUser", mappedBy="user")
* @var DoctrineCommonCollectionsCollection
*/
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;
}
相关-
- 相同的目标,略有不同的方法,一旦操作了结果集合,就会始终产生错误:http://www.doctrine-project.org/jira/browse/DDC-1323
- 支持该方法,无技术细节:条令2联接表+额外字段
我只找到了这种特定类型关系的实体定义的两个示例(请参阅问题),但没有关于如何使用它们的示例代码。因此,很不清楚由此产生的setters&getter是可以预期的。希望这段代码将有助于为其他进行类似尝试的人清理方法。
在这种情况下(感谢#doctrine@freenode)的理想解决方案是实现一个自定义存储库——一个更灵活的&创建&管理协会。
带有元数据类的联接表的示例自定义存储库-原始问题中的解决方案附带代码
<?php
use DoctrineORMEntityRepository;
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);
}
}
然后,从联接表类中,相应地修改Entity元数据,以指定自定义存储库
<?php
/**
* @Entity(repositoryClass="PathToGroupUserRepository")
*/
class GroupUser {
// ...
}
这将导致自定义存储库代替默认存储库,从而简化Entity类中的代理方法。
<?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);
}
}
事情和以前一样可控。