User,Group和Role表之间的ManyToMany导致__construct()必须是类型数组,对象给出错误

时间:2016-01-19 04:45:49

标签: php symfony fosuserbundle symfony-2.8

我正在使用FOSUserBundle(dev-master)在Symfony 2.8项目中工作,我正在尝试扩展一些事情,例如角色。为什么?因为我需要一个基于权限和角色的菜单系统,这是我发现实现这一目标的唯一方法。 (如果有人知道更好的一个请让我知道我对想法和建议持开放态度)。我现在正尝试在ManytoMany之间的User<->RoleManyToMany之间设置Group<->RoleRole是我为此目的创建的实体。下面是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;
            }
        }
    }
}

在此更改之前,一切都运行正常,我认为我可以创建一个新用户,升级到任何ROLE并登录系统。更改后,登录时我遇到的第一个错误是:

  

类型错误:传递给Symfony \ Component \ Security \ Core \ Authentication \ Token \ UsernamePasswordToken :: __ construct()的参数4必须是类型数组,给定对象,调用   第96行/var/www/html/platform-cm/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php

我不确定会出现什么问题,能不能给我一些帮助来实现这个目标?

1 个答案:

答案 0 :(得分:2)

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

我知道您可能想要CRUD这些角色,并且您想要添加其他实体。但是有很多小案例可以在不改变任何代码的情况下CRUD ROLE,例如:

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

但是,如果仍然是你想要存档的东西,FOSUserBundle带有我认为你应该检查的组功能,在你当前的实体中你正在创建这个新的Role实体,但是bundle为Group实体提供了一个字段角色在其上存储许多角色。

如果我认为你的getRoles方法返回一个对象,当它假设返回一个字符串数组时,你的答案就是问题。