0

我在将用户角色存储到数据库时遇到问题。我正在使用此处编写的原始文件:http: //symfony.com/doc/current/book/security.html

在这里:http ://symfony.com/doc/current/cookbook/security/entity_provider.html

登录注销正在工作。我可以将用户保存到数据库中,但我不知道如何保存他的角色。是否有可能使用这些文件,或者我必须再制作一个单独提供此文件的文件?我不想使用 FOSUser Bundle ...谢谢您的回答。以下是链接:

AccountController http://pastebin.com/ycrLyUcg

注册 http://pastebin.com/Q7se6pnF

注册 类型 http://pastebin.com/926tu0hj

用户 http://pastebin.com/aNdQr46C 角色 http://pastebin.com/cg7QTk59用户 存储库 http://pastebin.com/LHPuy4We

非常感谢您的回答

编辑 10.11.2013 23:00:

编辑 11.11.2013 15:20

4

2 回答 2

8

在您的 AccountController 的createAction方法中,您实际上从未将 a 分配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);
    ...
}

另外,我会重新考虑在UsersRoles@ManyToMany之间建立关系的要求,在这里可能就足够了;无论您是否希望坚持使用任何类型的关联映射,您都可能需要确保在持久化类时关联的角色也被持久化。为此,您可能需要在课堂上添加指令,如下所示:@ManyToOneUsercascadeUser

class User implements AdvancedUserInterface, \Serializable
{
    ...

    /**
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="users", cascade={"all"})
     */
    private $roles;

    ...
}

中的默认UserSymfony\Component\Security\Core\User还为其用户对象使用角色集合,因此一旦您拥有持久的角色,您就可以只使用现有的UsernameAuthenticationProvider,希望一切都能正常工作。如果不是,您可能必须自定义身份验证提供程序。

请注意,在上面我们使用方法显式分配$roles属性setRoles();这是因为返回类型getRoles()不是ArrayCollection,而是原始类型array。如果您希望一切都与 Symfony 现有的身份验证提供程序一起“正常工作”,并且getRoles()返回原始数组据我所知是正确的。


重新审视同一问题(2013 年 11 月 10 日):

我按照你写的做了,但它试图写入 acme_roles 表,我在其中保存角色类型 - 管理员、用户 .... 但我想将用户的角色保存到 user_roles 表中 - 我在那里保存用户 ID和角色ID

鉴于您在聊天中的扩展评论中表明您想要的内容,我的方法是使用三个实体/表来模拟您的用户到角色的关系。这显然只是解决问题的一种方法。

您的表将是:(acme_users实体User)、acme_rolesRole实体)和acme_user_rolesUserRole实体)。

  • User不会直接与您的对象建立多对多关系Role,而是可以在 the和类之间建立一对多关系。UserUserRole
  • 关联类UserRole(或任何你称之为的)需要一个主键 ( id) 和两个多对一关系:一个用于 the User,一个用于Role.
  • 无需在Role类和之间创建反向关系UserRole,因为您的角色与其他实体隔离。
  • 在将 a 分配Role给您新创建的之前,User您需要先查找它,一旦找到它,您可以使用您UserRole的引用创建您的$user$role然后将其添加到您在User班级中的角色集中。

以上只是您如何解决问题的粗略概述;更详细地说:

  1. 您的类应通过注释User将关系映射到实体,例如:UserRole@ORM\OneToMany

        /**
         * @ORM\OneToMany(targetEntity="UserRole", mappedBy="user", cascade={"all"})
         */
        private $userRoles;
    
  2. User中,更改您的getRoles()方法以返回与 关联的实际角色UserRoles,类似于:

        /**
         * @inheritDoc
         */
        public function getRoles()
        {
            $roles = array();
            foreach ($this->userRoles as $userRole) {
                $roles[] = $userRole->getRole();
            }
            return $roles;
        }
    
  3. User类中,添加getUserRoles()setUserRoles()(可能还有一个addUserRole())方法,删除setRoles()

  4. UserRole中,您想要存储实体引用而不是 ID(由于 Doctrine,它们将以任何方式映射为列中的 ID),因此只需分别更改$user_id$role_id$user$role,并更改它们的映射(如果您希望多个角色可分配通过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;
    
  5. $users从您的Role班级中删除所有引用。

  6. 在 中AccoundController,查找您要分配的角色(即,如果您要分配ROLE_USER查找正确和相应的角色),并将其分配给您的UserRole,然后将您的分配UserRole给您的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();
    
  7. 确保重新生成架构,最直接的方法是运行:

    $ 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
    
于 2013-11-06T02:15:54.163 回答
1

于是问题就解决了。我使用了本教程中的文件:http: //symfony.com/doc/current/cookbook/security/entity_provider.html。而不是我必须这样做:

$ php 应用程序/控制台原则:数据库:drop --force

$ php 应用程序/控制台原则:数据库:创建

$ php 应用程序/控制台原则:schema:drop --force

$ php 应用程序/控制台原则:模式:创建

$ php 应用程序/控制台原则:模式:验证

谢谢肖恩·奎恩

于 2013-11-22T16:36:07.667 回答