用户、组和角色之间的 ManyToMany table 导致 __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<->RoleGroup<->Role 之间设置 ManytoManyManyToManyRole 是我为此目的创建的实体。下面是 Role 实体的代码(为了不让 post 太长,我删除了一些注释):

/**
 * @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;
            }
        }
    }
}

在此更改之前一切正常,我的意思是我可以创建一个新用户,提升为任何角色并登录系统。更改后,我在登录时遇到的第一个错误是:

Type error: Argument 4 passed to Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken::__construct() must be of the type array, object given, called in /var/www/html/platform-cm/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php on line 96

我不确定哪里出了问题,能帮我实现这个目标吗?

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

我知道您可能想要对这些角色进行增删改查,为此您想要添加其他实体。但是有很多小案例,您可以在不更改任何代码的情况下对 ROLE 进行增删改查,例如:

您有一些菜单可以显示用户是否具有角色 PLAYER,但是您可以通过这个新实体创建角色 MULTI_PLAYER,但是您需要对 MULTI_PLAYER 菜单、控制器进行编码,业务逻辑要短。所以我的建议是不要将 ROLES 复杂化,因为它总是绑定到代码功能。

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

你的问题的答案我是否正确它是你的 getRoles 方法它 returning 一个对象,当它假设 return 一个字符串数组。