【问题标题】:Symfony2 set user role default User and Role filesSymfony2 设置用户角色默认用户和角色文件
【发布时间】:2013-11-05 16:53:50
【问题描述】:

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

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

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

帐户控制器 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

【问题讨论】:

  • 你坚持的用户模型是什么样的?您可能只需要将角色字段映射到模型以便可以持久化,并在持久化之前为用户设置角色。
  • 我想,它被映射了。它是用来登录的。那我该怎么做呢?
  • 你是什么意思?哪些文件?
  • 对不起,删除了我上面的评论;第二个链接(实体提供者)是否代表您的用户模型?
  • 前两个链接是教程,我用过。我忘了发布用户、角色和用户存储库。我会将其添加到我的问题中。编辑:添加链接

标签: php symfony doctrine-orm


【解决方案1】:

在您的 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_usersUser 实体)、acme_rolesRole 实体)和acme_user_rolesUserRole 实体)。

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

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

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

        /**
         * @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 和 @ 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;
    
  5. Role 类中删除对$users 的所有引用。

  6. 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();
    
  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
    

【讨论】:

  • 我会试试的。它可能会起作用。但首先我必须进行有效的 Doctrine2 扩展。我试图添加它们,但它写道:致命错误:在/data/web/virtuals/48565/virtual/www/domains/kozusnikjan.com/Symfony/app/cache 中找不到类'Gedmo\Tree\TreeListener' /prod/appProdDebugProjectContainer.php 在第 1377 行我正在谷歌搜索并试图解决问题,但没有成功。你有什么想法吗?
  • 看起来您可能已经更新了捆绑包,但生成的缓存较旧。或者您没有在 composer.json 中包含新的依赖项。我会尝试使用 composer 任务更新所有供应商捆绑包(包括 Doctrine),并让它重新生成您的缓存。您可能需要手动删除缓存。
  • 我试过 'php composer.phar install' 但没有效果。我试过删除缓存。还是不行。
  • 那该怎么办呢?
  • 您可能想尝试使用 composer update 命令,install 只需使用您的 composer.lock 文件 IIRC 中已解析的依赖项。在此处阅读有关 composer 选项的更多信息:getcomposer.org/doc/03-cli.md,我也通过 Symfony console 脚本运行我的所有命令,您也可以尝试一下 (symfony.com/doc/current/components/console/index.html)
【解决方案2】:

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

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

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

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

$ php 应用程序/控制台原则:schema:create

$ php 应用程序/控制台原则:schema:validate

谢谢肖恩·奎恩

【讨论】:

  • 很高兴我能帮助您找到正确的地方,即使我的解决方案不是您需要的那个! :)
猜你喜欢
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多