Symfony新手。如何使用Doctrine从数据库加载当前登录用户的角色。我有3张桌子。
users
=> (user_id, username, password, email
)
user_roles
=> (id,user_id,role_id
)
roles
=> (role_id, role_name
)
我为每个表都有实体及其相应的存储库。
我的security.yaml看起来像这样。
security:
encoders:
App\Entity\User:
algorithm: bcrypt
providers:
our_db_provider:
entity:
class: App\Entity\User
property: username
# if you're using multiple entity managers
# manager_name: customer
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
# pattern: ^/
# http_basic: ~
provider: our_db_provider
anonymous: true
form_login:
#login_path is GET request used ti display the form
# needs to be route names(alias) not the path.
login_path: login
#check_path is a POST request
check_path: logincheck
use_forward: true
default_target_path: default
always_use_default_target_path: true
我的Entity/User
实现了UserInterface
组件,通过阅读文档,我发现getRoles()
方法负责更新用户角色。我在getUserRoles($id)
中创建了一个名为UserRolesRepository.php
的自定义方法,我设法返回当前用户角色的字符串数组,但是我无法从Entity
访问此方法。我知道我不应该从Entity类访问Repository方法,但是我在这个阶段非常困难。所以现在我的getRoles()
方法返回静态数组return array('ROLE_ADMIN', 'ROLE_EDITOR');
我的User
实体类
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use App\Repository\UserRolesRepository;
use Doctrine\ORM\EntityRepository;
use App\Services\Helper;
/**
* @ORM\Table(name="`user`")
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User implements UserInterface, \Serializable
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=25, nullable=true)
*/
private $username;
/**
* @ORM\Column(type="string", length=64, nullable=true)
*/
private $password;
/**
* @ORM\Column(type="string", length=254, nullable=true)
*/
private $email;
/**
* @ORM\Column(type="boolean", nullable=true)
*/
private $isActive;
private $roles;
/**
* @ORM\Column(type="string", length=254, nullable=true)
*/
private $role;
public function __construct()
{
$this->isActive = true;
}
/**
* @return mixed
*/
public function getRole()
{
return $this->role;
}
/**
* @param mixed $role
*/
public function setRole($role)
{
$this->role = $role;
}
public function getId()
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(?string $username): self
{
$this->username = $username;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(?string $password): self
{
$this->password = $password;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(?string $email): self
{
$this->email = $email;
return $this;
}
public function getIsActive(): ?bool
{
return $this->isActive;
}
public function setIsActive(?bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
//return is required or else returns an fatal error.
public function getRoles()
{
return array('ROLE_ADMIN','ROLE_EDITOR');
}
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
public function serialize()
{
// TODO: Implement serialize() method.
return serialize(array(
$this->id,
$this->username,
$this->password,
));
}
/** @see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt
) = unserialize($serialized, ['allowed_classes' => false]);
}
public function getSalt()
{
// TODO: Implement getSalt() method.
return null;
}
}
答案 0 :(得分:1)
到目前为止,您尚未根据数据库结构将用户映射到角色。
private $roles;
没有关于它如何映射到角色表的信息。它应该看起来像:
/**
* @var Collection|Role[]
* @ORM\ManyToMany(targetEntity="Role")
* @ORM\JoinTable(
* name="user_roles",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}
* )
*/
private $roles;
您还需要在构造中创建一组初始角色,以便getRoles
不会抛出错误,以便在需要时逐个将角色添加到新用户:
public function __construct()
{
$this->isActive = true;
$this->roles = new ArrayCollection();
}
您可以删除getRole()
和setRole()
,因为我们没有一个角色(除非界面要求它),您可能会丢失当前{{1 property:
$role
但添加一个收集集合的setter:
/**
* @ORM\Column(type="string", length=254, nullable=true)
*/
private $role;
然后获得角色:
public function setRoles(Collection $roles)
{
$this->roles = $roles;
}
如果您正在使用表单创建用户(尤其是Sonata Admin one),除了添加和删除用户的单个角色之外,您还可以使用以下方法(它将删除用户与用户之间的关系)角色,而不是角色本身):
public function getRoles()
{
return $this->roles->toArray();
}
一个删除角色:
public function addRole(Role $role)
{
$this->roles->add($role);
}
答案 1 :(得分:0)
Symfony角色与安全选民密切合作。如果你改变了在Symfony中进行角色管理的标准方式(不使用ROLE_SOMETHING),那么你应该做三件事:
映射getRoles
getter以返回User类中的Roles对象集合。使用doctrine,您可以轻松地将关系映射到ManyToMany。
然后,您必须创建一个GuardAuthenticator并覆盖createAuthenticatedToken
方法,因此您将自定义角色传递给Symfony的Auth Token(它是负责应用程序中访问控制的类)。
您必须实施一个安全投票人,可以从数据库中获取角色,并在用户可以做某事的情况下进行投票。
正如您所看到的,所有这些都非常复杂,但并非不可能。 Symfony的内置角色系统足以满足您的需求。
答案 2 :(得分:0)
这是在Symfony 4中将2个表与多个用户相关联的解决方案
//Entity Usuarios
/**
* @var \Role
*
* @ORM\ManyToOne(targetEntity="Role")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="Role_id", referencedColumnName="id")
* })
*/
private $role;
这就是方法getRoles()
public function getRoles()
{
//return array('ROLE_USER');
return array($this->role->getRol());
}
通过这种方式,数组返回登录用户的角色