Запросите отношения многие ко многим, используя тонкий каркас и доктрину - PullRequest
0 голосов
/ 25 января 2019

Я использую Slim Framework с Doctrine. У меня есть три таблицы

id | username | password | name
--------------------------------
1  | Lorel    | ******** | Lorel

id | permission  | description
-------------------------------
2  | READ_ACCESS | Lorel Ipsum


id | user_id | permission_id
-----------------------------
X  | 1       | 2

Есть ли в любом случае использование доктрины, с помощью которой я могу выяснить, предположим, есть ли у пользователя "1" разрешение "2".

1 Ответ

0 голосов
/ 26 января 2019

Я предполагаю, что вы ищете для авторизации. У меня есть настройка, которая делает это в 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

...