Класс пользовательского репозитория как пользовательский провайдер и внедрение зависимостей

Я следую этому руководству (Как аутентифицировать пользователей с помощью ключей API) для реализации ключей API в моем приложении.

Я использую свой класс пользовательского репозитория, который был создан на основе этого tutorial (Как загрузить пользователей безопасности из базы данных) в качестве поставщика пользователей, необходимого в процессе предварительной аутентификации, поскольку этот класс уже имеет методы, описанные как необходимые от поставщика пользователей в учебнике. Я слежу, а именно loadUserByUsername(), refreshUser() и supportsClass().

Symfony вызывает мою службу apikey_authenticator, которая требует провайдера пользователя в качестве аргумента. Из-за этого я настроил другую службу под названием userprovider, которая является моим классом пользовательского репозитория, например:

services:
apikey_authenticator:
    class: MyBundle\Security\ApiKeyAuthenticator
    arguments: ["@userprovider"]
userprovider:
    class: MyBundle\Entity\UserRepository

Но мой класс пользовательского репозитория зависит от диспетчера сущностей, который я не знаю, как внедрить. Конфигурация моей доктрины — это конфигурация по умолчанию, которая поставляется с symfony:

# Doctrine Configuration
doctrine:
dbal:
    driver:   "%database_driver%"
    host:     "%database_host%"
    port:     "%database_port%"
    dbname:   "%database_name%"
    user:     "%database_user%"
    password: "%database_password%"
    charset:  UTF8

orm:
    auto_generate_proxy_classes: "%kernel.debug%"
    auto_mapping: true

Как я могу это решить? И стоит ли в этом случае использовать класс пользовательского репозитория в качестве провайдера пользователя?


person Yuri Borges    schedule 01.05.2014    source источник


Ответы (2)


Репозитории сущностей Doctrine создаются с помощью фабрики. Вот пример:

cerad_game__game_repository__doctrine:
    class:  Cerad\Bundle\GameBundle\Doctrine\EntityRepository\GameRepository
    factory_service: 'doctrine.orm.default_entity_manager'
    factory_method:  'getRepository'
    arguments:  
        - 'Cerad\Bundle\GameBundle\Doctrine\Entity\Game'

Это хорошая идея? Может быть, было бы чище внедрить репозиторий в класс UserProvider вместо того, чтобы загромождать репозиторий методами UserProvider. Но в любом случае будет работать.

person Cerad    schedule 01.05.2014

Просто хотел добавить свой 2c, так как я следовал тем руководствам, которые вы упомянули.

Я определил класс Authenticator и провайдера. Аутентификатор выполняет только необходимые проверки безопасности, а провайдер обрабатывает соединения с базой данных (например, возвращая пользователя по токену).

В __construct моего провайдера у меня есть это:

protected $em;
protected $repositoryClass = 'myrepoclass';
protected $repository;

public function __construct(EntityManager $em) {
    $this->em = $em;
    $this->repository = $this->em->getRepository($this->repositoryClass);
}

Теперь я могу просто вызывать такие запросы, как $this->repository->findOneById($id); Я явно определил класс репозитория, потому что я думаю, что он позволяет легче переключаться на другой объект, если это необходимо (конечно, может быть неправильное мышление).

В моем файле служб у меня есть это:

api_user_provider:
  class: "%api_user_provider.class%"
  arguments: ["@doctrine.orm.entity_manager"]

api_user_authenticator:
  class: "%api_user_authenticator.class%"
  arguments: ["@api_user_provider"]

Класс провайдера не совпадает (по крайней мере, для меня) с классом сущности. Я их разделил, потому что думаю, что работает чище.

Ну, я так все устроил. Надеюсь это поможет :)

редактировать: поскольку я создал отдельный пакет (ApiBundle и UserBundle), я отделил поставщика от класса сущности. Я также следовал руководству по «загрузке пользователей безопасности из базы данных», и это последнее, что я придумал для реализации аутентификации токена API. Хотя у вас уже есть те же методы в вашем репозитории, я все же думаю, что лучше отделить их от вашего класса репозитория, как это сделал я (это, конечно, зависит от ваших потребностей), так как я думаю, что это работает чище. Конечно, вам решать, что делать :)

person Wcool    schedule 02.05.2014
comment
Может быть, было бы чище внедрить репозиторий напрямую, а не менеджер сущностей. См. мой ответ для примера того, как настроить службу репозитория. - person Cerad; 03.05.2014