使用元数据影响获取者/设置者连接表-原则2



我正在编写一个功能,该功能要求联接表的记录携带额外的元数据(使用元数据联接表)。我试图根据条令文件的这一部分来实现这一点。

请参阅下面的实体定义示例

现在的挑战是getGroupssetGroups不产生/设置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);
    }
}

事情和以前一样可控。

最新更新