在您的 AccountController 的 createAction 方法中,您实际上从未将 Role 分配给用户;您必须先设置它,然后才能将其用作身份验证过程的一部分。鉴于您的上述模型,这样的事情应该坚持Role。
if ($registrationForm->isValid()) {
...
$role = new Role();
$role->setName('User');
$role->setRole('ROLE_USER');
$roles = new \Doctrine\Common\Collections\ArrayCollection;
$roles->add($role);
$user->setRoles($roles);
...
}
另外,我会重新考虑在用户和角色之间建立@ManyToMany关系的要求,@ManyToOne在这里可能就足够了;无论您是否希望坚持使用任何类型的关联映射,您都可能需要确保当您持久化 User 类时,关联的角色也会被持久化。为此,您可能需要在 User 类中添加 cascade 指令,如下所示:
class User implements AdvancedUserInterface, \Serializable
{
...
/**
* @ORM\ManyToMany(targetEntity="Role", inversedBy="users", cascade={"all"})
*/
private $roles;
...
}
Symfony\Component\Security\Core\User 中的默认 User 类也为其用户对象使用角色集合,因此一旦您拥有持久的角色,您就可以只使用现有的 UsernameAuthenticationProvider,希望一切都会只是工作。如果不是,您可能必须自定义身份验证提供程序。
请注意,在上面我们使用setRoles() 方法显式分配$roles 属性;这是因为getRoles() 的返回类型不是ArrayCollection,而是原语array。如果您希望一切都与 Symfony 现有的具有 getRoles() 的身份验证提供程序一起“正常工作”,那么据我所知,原始数组是正确的。
重新审视同一问题(2013 年 11 月 10 日):
"我按照你写的做了,但它试图写入 acme_roles 表,我在其中保存角色类型 - 管理员、用户 .... 但我想将用户的角色保存到 user_roles 表中- 我在那里保存用户 ID 和角色 ID"
鉴于您在聊天中的扩展 cmets 中表明您想要的内容,我的方法是使用三个实体/表来模拟您的用户到角色的关系。这显然只是解决问题的一种方法。
您的表将是:acme_users(User 实体)、acme_roles(Role 实体)和acme_user_roles(UserRole 实体)。
- 您的
User 不会直接与您的Role 对象建立多对多关系,而是可以在User 和一个对象之间建立一对多 关系UserRole 班级。
- 关联类
UserRole(或其他任何名称)需要一个主键(id)和两个多对一关系:一个用于User,一个用于Role。
- 没有必要在
Role 类和 UserRole 之间创建反向关系,因为您的角色与其他实体隔离。
- 在将
Role 分配给您新创建的User 之前,您需要先查找它,一旦找到它,您可以创建您的UserRole,并引用您的$user 和$role,然后将其添加到您在 User 类中的角色集。
以上只是您如何解决问题的粗略概述;更详细:
-
您的User 类应通过@ORM\OneToMany 注释将关系映射到UserRole 实体,例如:
/**
* @ORM\OneToMany(targetEntity="UserRole", mappedBy="user", cascade={"all"})
*/
private $userRoles;
-
在User 中,更改getRoles() 方法以返回与UserRoles 关联的实际角色,类似于:
/**
* @inheritDoc
*/
public function getRoles()
{
$roles = array();
foreach ($this->userRoles as $userRole) {
$roles[] = $userRole->getRole();
}
return $roles;
}
在User 类中,添加getUserRoles()、setUserRoles()(可能还有addUserRole())方法,删除setRoles()
-
在UserRole 中,您希望存储实体引用而不是 ID(由于 Doctrine,它们将以任何方式映射为列中的 ID),因此只需将 $user_id 和 $role_id 更改为 $user 和 @ 987654381@ 并更改它们的映射(如果您希望通过UserRole 关联分配多个角色,您需要有一个离散的身份/主键,因此添加$id 属性),如下所示:
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="userRoles", cascade={"all"})
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity="Role", cascade={"all"})
*/
private $role;
从Role 类中删除对$users 的所有引用。
-
在AccoundController 中,查找您要分配的角色(即,如果您要分配ROLE_USER,请查找正确和对应的角色),并将其分配给您的UserRole,然后分配您的@987654390 @给你的User,最后坚持你的$user,例如:
$user = $registration->getUser();
$user->setSalt($this->generateSalt());
$user->setIsActive(1);
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword($user->getPassword(), $user->getSalt());
$user->setPassword($password);
$role = $this->getDoctrine()
->getRepository('AcmeAccountBundle:Role')
->find(2); // Finds "ROLE_USER"
$userRole = new UserRole();
$userRole->setRole($role);
$user->addUserRole($userRole);
$em->persist($user);
$em->flush();
-
确保重新生成架构,最直接的方法是运行:
$ php app/console doctrine:database:drop --force
$ php app/console doctrine:database:create
$ php app/console doctrine:schema:drop --force
$ php app/console doctrine:schema:create
$ php app/console doctrine:schema:validate