我正在使用FOSUserBundle(dev-master)在Symfony 2.8项目中工作,我正在尝试扩展一些事情,例如角色。为什么?因为我需要一个基于权限和角色的菜单系统,这是我发现实现这一目标的唯一方法。 (如果有人知道更好的一个请让我知道我对想法和建议持开放态度)。我现在正尝试在ManytoMany
之间的User<->Role
和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;
}
}
}
}
在此更改之前,一切都运行正常,我认为我可以创建一个新用户,升级到任何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
我不确定会出现什么问题,能不能给我一些帮助来实现这个目标?
答案 0 :(得分:2)
要归档您不需要创建另一个表的多个角色,实现Symfony AdvancedUserInterface的FOSUserBundle提供的实体具有映射为数组的角色字段,您可以在其上设置多个角色。
我知道您可能想要CRUD这些角色,并且您想要添加其他实体。但是有很多小案例可以在不改变任何代码的情况下CRUD ROLE,例如:
您有一些菜单显示用户是否具有角色PLAYER但是您通过这个新实体创建了角色MULTI_PLAYER,但您需要将MULTI_PLAYER菜单,控制器和业务逻辑编码为短。所以我的建议是不要让很多ROLES复杂化,因为它总是会绑定到代码功能。
但是,如果仍然是你想要存档的东西,FOSUserBundle带有我认为你应该检查的组功能,在你当前的实体中你正在创建这个新的Role实体,但是bundle为Group实体提供了一个字段角色在其上存储许多角色。
如果我认为你的getRoles方法返回一个对象,当它假设返回一个字符串数组时,你的答案就是问题。