Учение Symfony 4, Как загрузить роли пользователя из базы данных - PullRequest
0 голосов
/ 26 апреля 2018

Новое в 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

My Entity/User реализует компонент UserInterface, и, читая документы, я узнал, что метод getRoles() отвечает за обновление ролей пользователей. Я создал пользовательский метод с именем getUserRoles($id) в моем UserRolesRepository.php, где мне удалось вернуть строковый массив ролей текущего пользователя, однако я не могу получить доступ к этому методу из Entity. Я знаю, что не должен получать доступ к методам Repository из класса Entity, но я очень застрял на этом этапе. Так что сейчас мой 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;
}
}

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Пока что вы не сопоставили своего пользователя с ролями согласно структуре вашей базы данных.

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(), потому что у нас нет ни одной роли (если это не требуется интерфейсом), и вы можете потерять текущее свойство $role:

/**
 * @ORM\Column(type="string", length=254, nullable=true)
 */
private $role;

но добавьте сеттер, который принимает коллекцию:

public function setRoles(Collection $roles)
{
    $this->roles = $roles;
}

Тогда, чтобы получить роли:

public function getRoles()
{
    return $this->roles->toArray();
}

Если вы используете форму для создания пользователя (особенно Sonata Admin), вы можете использовать следующие методы в дополнение к добавлению и удалению отдельных ролей пользователя (это приведет к удалению отношения между пользователем и ролью). , а не сама роль):

public function addRole(Role $role)
{
    $this->roles->add($role);
}

И один, чтобы удалить роль:

public function removeRole(Role $role)
{
    $this->roles->removeElement($role);
}
0 голосов
/ 12 декабря 2018

Это решение для связи двух таблиц с несколькими пользователями в Symfony 4

//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());
}

Таким образом, массив возвращает Роль вошедшего в систему пользователя

0 голосов
/ 26 апреля 2018

Роли Symfony работают в тесном контакте с избирателями безопасности. Если вы измените стандартный способ управления ролями в Symfony (не используйте ROLE_SOMETHING), вам следует сделать три вещи:

  1. Сопоставьте получатель getRoles, чтобы получить коллекцию объектов Roles в вашем классе User. Используя доктрину, вы можете легко сопоставить отношения с ManyToMany.

  2. Затем вам нужно создать GuardAuthenticator и переопределить метод createAuthenticatedToken, чтобы передать пользовательские роли, которые вы выполнили, токену Symfony (который является классом, отвечающим за контроль доступа в вашем приложении).

  3. Вы должны реализовать защитного избирателя, который может извлекать роли из базы данных и голосовать, если пользователь может или не может сделать определенную вещь.

Как видите, все это очень сложно, но не невозможно. Я думаю, что встроенной системы ролей Symfony более чем достаточно для удовлетворения ваших потребностей.

...