【问题标题】:Symfony get user defined with different classes for rolesSymfony 使用不同的角色类来定义用户
【发布时间】:2015-11-23 21:14:42
【问题描述】:

我的应用程序中有两个角色,例如ROLE_USERROLE_SUPERUSER。用户使用 Doctrine 存储在数据库中。具有ROLE_USER 角色的用户基于一个简单的User 类。 (为便于阅读,Getter 和 setter 已被删除。)

Acme\MyBundle\Entity\User.php

namespace Acme\MyBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
 
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
 
/**
* @ORM\Entity
* @ORM\Entity(repositoryClass="Acme\MyBundle\Entity\UserRepository")
* @ORM\Table("users")
* @UniqueEntity(
*       fields={"email"},
*       message="email already used"
* )
*/
class User implements UserInterface, \Serializable
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
 
    /**
     * @ORM\Column(type="string", length=255, unique=true)
     * @Assert\NotBlank()
     * @Assert\Email()
     */
    protected $email;
 
    /**
     * @ORM\Column(type="string", length=32)
     */
    private $salt;
 
    /**
     * @ORM\Column(type="string", length=4096)
     */
    private $password;
 
 
    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;
 
 
    public function __construct()
    {
        $this->isActive = true;
        $this->salt = md5(uniqid(null, true));
    }
 
    /**
    * @inheritDoc
    */
    public function getRoles()
    {
    return array('ROLE_USER','ROLE_SUPERUSER');
    }
 
}

我有一个 SuperUser 类,它扩展了 User 以提供只有 ROLE_SUPERUSER 的用户才需要的更多字段。

Acme\MyBundle\Entity\SuperUser.php

namespace Acme\MyBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
 
use Symfony\Component\Validator\Constraints as Assert;
 
 
/**
 * @ORM\Entity
 * @ORM\Table(name="super_users")
 */
class SuperUser extends User
{
 
    /**
     * @var integer
     */
    protected $id;
 
    /**
     * @var string
     */
    protected $email;
 
 
    /**
     * @ORM\Column(type="string", length=32)
     */
    proteced $avatar;
 
 
    /**
     * @ORM\Column(type="string", length=50, unique=true)
     */
    proteced $username;
 
}

在我的控制器中,我使用$user = $this -> getUser(); 来获取当前用户,但这会返回User 类的实例,并且我无法访问SuperUser 属性或方法,即使用户具有@ 角色987654333@.

例如,我希望能够使用以下代码。

if ($this->get('security.context')->isGranted('ROLE_SUPERUSER')) {
    $avatar = $this->getUser()-> avatar;
}

有没有办法做到这一点?我想说这与教义关系有关,但我真的不知道要改变什么。

顺便说一句,正如您所见,我的标准 User 类中没有 username 字段,它只存在于 SuperUser 中。由于身份验证基于username,这是否会导致任何问题?


我觉得我的问题还没有明确暴露,但这可能是由于我当前的代码,这是错误的。

我没有两个用户表。我只想要一个 User 类(带有一个 users 表)。认证只在这个类上操作,有邮箱和密码。
我有另一个类SuperUser```that provides extra fields to users that have the ROLE_SUPERUSER`` 角色,但超级用户是用户并且在 users 表中有一个条目。我只想在相关行上创建一个左连接,这就是我使用继承的原因。 (也许有更好的方法。)

如果我想获取所有电子邮件,我可以查询 users 表。如果我想获取所有用户名,因为只有超级用户有一个,我可以查询 superusers 表。

【问题讨论】:

  • 我想建议您只保留一个用户类。添加一个名为 isSuperUser 的额外列来注册谁是普通用户,谁是超级用户。根据需要为超级用户提供尽可能多的额外列,但请确保此列的值可能为 NULL
  • 我认为这不是一个好习惯。它违背了面向对象编程的基本原理,并创建了不一致的数据模型。
  • 没有。它不是。如果用户登录怎么办。如果用户存在并输入正确的密码,您想检查两个表。如果您想按字母顺序显示用户列表怎么办?大多数初学者都想经常扩展一个类。实际上只有少数情况可以使用extend关键字。
  • 好的。从你所说的和下面的答案来看,我认为我误解了这个问题。我正在编辑我的帖子。

标签: symfony inheritance doctrine-orm roles


【解决方案1】:

你应该有两个用户提供者,并使用一个主提供者:

security:
    providers:
        master_provider:
            chain:
                providers: [user, super_user]

        user:
            entity: { class: Acme\MyBundle\Entity\User, property: username }
        super_user:
            entity: { class: Acme\MyBundle\Entity\SuperUser, property: username }

        firewalls:
            main:
                provider: master_provider

http://symfony.com/doc/current/cookbook/security/multiple_user_providers.html

【讨论】:

    【解决方案2】:

    我会选择两个具有 OneToOne 关系的实体(无扩展)

    /** @Entity **/
    class SuperUser
    {
        // ...
    
        /**
         * @ORM\OneToOne(targetEntity="User", mappedBy="superUser")
         **/
        private $user;
    
        // ...
    }
    
    /** @Entity **/
    class User
    {
        // ...
    
        /**
         * @ORM\OneToOne(targetEntity="SuperUser", inversedBy="user")
         * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
         **/
        private $superUser;
    
        // ...
    }
    

    要不然看看Inheritance Mapping

    【讨论】:

    • 这很好用,除了我必须使用$user->getSuperUser->getUsername() 来获取用户名,而且我希望只能使用$user->getUsername() 来完成,这就是我尝试扩展的原因。
    • 没错,但是学说的基本规则是一个实体==一个表。您可以在 User 实体中添加一个方法 getUsername() { if($user) return $user->getUsername();否则返回 NULL; }
    猜你喜欢
    • 2018-10-16
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 2022-01-13
    • 1970-01-01
    • 2019-03-29
    相关资源
    最近更新 更多