Я предполагаю, что вы ищете для авторизации. У меня есть настройка, которая делает это в Zend Framework 3 с Doctrine 2. Отношения одинаковы, просто не знаю, как перевести это на Slim Framework. Но здесь ничего не идет ;-)
Пользователь Сущность имеет отношение к ролям:
/**
* @var Collection|ArrayCollection|Role[]
* @ORM\ManyToMany(targetEntity="User\Entity\Role", inversedBy="users", fetch="LAZY")
* @ORM\JoinTable(
* name="user_user_roles",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}
* )
*
*/
protected $roles;
Роль У объекта есть Маршруты и обратная сторона к Пользователь
/**
* @var Collection|ArrayCollection|Route[]
* @ORM\ManyToMany(targetEntity="User\Entity\Route", inversedBy="roles", fetch="EAGER")
* @ORM\JoinTable(
* name="user_role_routes",
* joinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="route_id", referencedColumnName="id")}
* )
*/
protected $routes;
/**
* @var Collection|ArrayCollection|User[]
* @ORM\ManyToMany(targetEntity="User\Entity\User", mappedBy="roles", fetch="LAZY")
*/
protected $users;
Маршрут У сущности есть обратное значение Роль
/**
* @var Collection|ArrayCollection|Role[]
* @ORM\ManyToMany(targetEntity="User\Entity\Role", mappedBy="routes", fetch="LAZY")
*/
protected $roles;
Обратите внимание, что это касается 2 отношений:
- Пользователь <-> Роль
- Роль <-> Маршрут
Обязательно инициализируйте каждую коллекцию в __construct
, например:
// Initialize only those within the Entity
public function __construct()
{
$this->users = new ArrayCollection();
}
Создайте свой метод получения (метод установки не требуется!). Создайте методы Adder / Remover вместо установщика, вот так (это в пределах Route Entity):
/**
* @param Collection|ArrayCollection|Role[] $roles
*
* @return Route
*/
public function addRoles(Collection $roles) : Route
{
foreach ($roles as $role) {
if ( ! $this->getRoles()->contains($role)) {
$this->getRoles()->add($role);
}
if ( ! $role->getRoutes()->contains($this)) {
$role->getRoutes()->add($this);
}
}
return $this;
}
/**
* @param Collection|ArrayCollection|Role[] $roles
*
* @return Route
*/
public function removeRoles(Collection $roles) : Route
{
foreach ($roles as $role) {
if ($this->getRoles()->contains($role)) {
$this->getRoles()->remove($role);
}
if ($role->getRoutes()->contains($this)) {
$role->getRoutes()->remove($this);
}
}
return $this;
}
Итак, поехали, это настройка. Я бы посоветовал вам включить расширения Gedmo Doctrine и применить @Gedmo\Tree(type="nested")
к вашей роли сущности. Упрощает управление (вложенными / унаследованными) ролями. См. Управление иерархическими данными в MySQL (и Документы Gedmo Tree )
Чтобы проверить, есть ли у пользователя доступ к определенному маршруту, вам потребуется некоторая форма службы аутентификации. Поскольку я не знаю Слима, убедитесь, что вы заполнили это чем-то из этих рамок. Логика та же, хотя. Я использую сервис, который должен быть включен / использован при доступе к маршруту, который проверяет, известен ли пользователь (аутентифицирован) и, если нет, назначает гостевую роль, а затем проверяет, известен ли доступ к маршруту для какой-либо из назначенных ролей.
/**
* @param string $route
*
* @return bool
* @throws Exception
*/
public function isGranted(string $route) : bool
{
// Get assigned Role[] array or set Guest Role
if ($this->getAuthenticationService()->hasIdentity()) {
/** @var User $user */
$user = $this->getAuthenticationService()->getIdentity();
/** @var Collection|Role[] $roles */
$roles = $user->getRoles();
} else {
$roles = new ArrayCollection(
[
$this->getObjectManager()->getRepository(Role::class)->findOneBy(['name' => Role::NO_ACCOUNT_ROLE]),
]
);
}
foreach ($roles as $role) {
if ($this->checkRoutes($role, $route)) {
return true;
}
}
return false;
}
Итак, все вышеперечисленное должно принести вам больше, чем я бы сказал.
GL & HF