用户、组和角色表之间的 ManyToMany 导致 __construct() 必须是数组类型,对象给定错误


ManyToMany between User, Group and a Role table causes __construct() must be of the type array, object given error

我正在使用FOSUserBundle(dev-master)在Symfony 2.8项目中工作,我正在尝试扩展一些东西,例如角色。为什么?因为我需要一个基于权限和角色的菜单系统,这是我发现实现这一目标的唯一方法。(如果有人知道更好的,请让我知道我对想法和建议持开放态度)。现在我正在尝试在User<->RoleManyToMany之间设置ManytoMany Group<->Role. Role是我为此目的创建的实体。下面是Role实体的代码(我已经删除了一些评论,以免使帖子长):

/**
 * @ORM'Entity
 * @ORM'Table(name="fos_role")
 */
class Role
{
    use IdentifierAutogeneratedTrait;
    use Timestampable;
    use ActiveTrait;
    /**
     * @ORM'Column(type="string", length=150)
     */
    protected $name;
    /**
     * @ORM'Column(type="text", nullable=true)
     */
    protected $description;
    /**
     * @var User[]
     * @ORM'ManyToMany(targetEntity="User", mappedBy="roleUsers", cascade={"persist"})
     */
    protected $users;
    /**
     * @var Group[]
     * @ORM'ManyToMany(targetEntity="Group", mappedBy="roleGroups", cascade={"persist"})
     */
    protected $groups;
    public function __construct()
    {
        $this->users = new ArrayCollection();
        $this->groups = new ArrayCollection();
    }
    ... // getter and setter for common properties
    /**
     * @return User[]|ArrayCollection
     */
    public function getUsers()
    {
        return $this->users;
    }
    /**
     * @param User[] $users
     */
    public function setUsers($users)
    {
        $this->users->clear();
        $this->users = new ArrayCollection($users);
    }
    /**
     * @param $user User The user to associate
     */
    public function addUser($user)
    {
        if (!$this->users->contains($user)) {
            $this->users[] = $user;
        }
    }
    /**
     * @param User $user
     */
    public function removeUser($user)
    {
        $this->users->removeElement($user);
    }
    /**
     * @param Group[] $groups
     */
    public function setGroups($groups)
    {
        $this->groups->clear();
        $this->groups = new ArrayCollection($groups);
    }
    /**
     * @param $group Group The group to associate
     */
    public function addGroup($group)
    {
        if (!$this->groups->contains($group)) {
            $this->groups[] = $group;
        }
    }
    /**
     * @param Group $group
     */
    public function removeGroup($group)
    {
        $this->groups->removeElement($group);
    }
}

这是User实体的代码(出于同样的原因再次删除一些注释):

use FOS'UserBundle'Model'User as BaseUser;
/**
 * @ORM'Entity
 * @ORM'Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM'Id
     * @ORM'Column(type="integer")
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM'ManyToMany(targetEntity="Group", inversedBy="users")
     * @ORM'JoinTable(name="fos_user_has_group",
     *      joinColumns={@ORM'JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM'JoinColumn(name="group_id", referencedColumnName="id")}
     * )
     */
    protected $groups;
    /**
     * @var Role[]
     * @ORM'ManyToMany(targetEntity="Role", inversedBy="users", cascade={"persist", "remove"})
     * @ORM'JoinTable(name="fos_user_has_role")
     */
    protected $roleUsers;
    public function __construct()
    {
        parent::__construct();
        $this->roleUsers = new ArrayCollection();
    }
    /**
     * @param $role Role the role to associate
     */
    public function addRol($role)
    {
        $role->addUser($this);
        if (!$this->roleUsers->contains($role)) {
            $this->roleUsers->add($role);
        }
    }
    /**
     * @param $role Role the role to remove
     */
    public function removeRol($role)
    {
        $role->removeCommand($this);
        $this->roleUsers->removeElement($role);
    }
    /**
     * @return Role[]
     */
    public function getRoles()
    {
        return $this->roleUsers;
    }
    /**
     * @param Role[] $role
     */
    public function setRole($role)
    {
        // This is the owning side, we have to call remove and add to have change in the alias side too.
        foreach ($this->getRoles() as $roles) {
            $this->removeRol($roles);
        }
        foreach ($roles as $role) {
            $this->addRol($role);
        }
    }
    /**
     * @param $id
     */
    public function removeAssociationById($id)
    {
        foreach ($this->roleUsers as $role) {
            if ($role->getId() == $id) {
                $this->roleUsers->removeElement($role);
                return;
            }
        }
    }
}

在此更改之前,一切都运行良好,总而言之,我的意思是我可以创建一个新用户,提升为任何角色并登录到系统。更改后,登录时我遇到的第一个错误是这个:

类型错误:传递给 Symfony''组件''安全性''核心''身份验证''令牌''用户名密码令牌::__construct() 的类型必须是数组类型,对象给定,调用 /var/www/html/platform-cm/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php on line 96

我不确定可能出了什么问题,可以给我一些帮助来实现这一点吗?

要存档多个角色,您不需要创建另一个表,由FOSUserBundle提供的实现Symfony AdvancedUserInterface的实体具有映射为数组的角色字段,您可以在其上设置多个角色。

我知道您可能希望 CRUD 这些角色,并为此添加其他实体。但是在很多小情况下,您可以在不更改任何代码段的情况下对角色进行 CRUD,例如:

您有一些菜单显示用户是否具有角色 PLAYER,但随后您通过此新实体创建角色MULTI_PLAYER,但您需要将MULTI_PLAYER菜单、控制器、业务逻辑编码为简短。所以我的建议是不要使太多角色复杂化,因为它将始终绑定到代码功能。

但是,如果仍然是您想要存档的内容,FOSUserBundle 附带了一个组功能,我认为您应该查看,在您当前的实体中,您正在创建这个新的角色实体,但捆绑包还为组实体提供了一个字段角色来存储许多角色。

你的问题的答案,如果

我是正确的,那就是你的getRoles方法在它应该返回一个字符串数组时返回一个对象。