web-dev-qa-db-fra.com

Symfony 2.0 obtient un service à l'intérieur de l'entité

Im seraching over et ne peut pas trouver de réponse. J'ai un modèle de rôle de base de données dans mon application. L'utilisateur peut avoir un rôle mais ce rôle doit être stocké dans la base de données.

Mais l'utilisateur doit avoir un rôle par défaut ajouté à partir de la base de données. J'ai donc créé un service:

<?php

namespace Alef\UserBundle\Service;

use Alef\UserBundle\Entity\Role;

/**
 * Description of RoleService
 *
 * @author Oracle
 */
class RoleService {

    const ENTITY_NAME = 'AlefUserBundle:Role';

    private $em;

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

    public function findAll()
    {
        return $this->em->getRepository(self::ENTITY_NAME)->findAll();
    }

    public function create(User $user)
    {
        // possibly validation here

        $this->em->persist($user);
        $this->em->flush($user);
    }

    public function addRole($name, $role) {
        if (($newrole = findRoleByRole($role)) != null)
            return $newrole;
        if (($newrole = findRoleByName($name)) != null)
            return $newrole;

        //there is no existing role
        $newrole = new Role();
        $newrole->setName($name);
        $newrole->setRole($role);

        $em->persist($newrole);
        $em->flush();

        return $newrole;
    }

    public function getRoleByName($name) {
        return $this->em->getRepository(self::ENTITY_NAME)->findBy(array('name' => $name));
    }

    public function getRoleByRole($role) {
        return $this->em->getRepository(self::ENTITY_NAME)->findBy(array('role' => $role));
    }

}

mon services.yml est:

alef.role_service:
    class: Alef\UserBundle\Service\RoleService
    arguments: [%doctrine.orm.entity_manager%]

Et maintenant, je veux l'utiliser à deux endroits: UserController et User entité. Comment puis-je les faire entrer dans l'entité? Quant au contrôleur, je pense que je dois juste:

$this->get('alef.role_service');

Mais comment obtenir un service à l'intérieur de l'entité?

35
Kaminari

Non. C'est une question très commune. Les entités ne doivent connaître que les autres entités et non le gestionnaire d'entité ou d'autres services de haut niveau. Cela peut être un peu difficile de faire la transition vers cette façon de se développer, mais cela en vaut généralement la peine.

Ce que vous voulez faire, c'est charger le rôle lorsque vous chargez l'utilisateur. En règle générale, vous vous retrouverez avec un UserProvider qui fait ce genre de chose. Avez-vous lu les sections sur la sécurité? Cela devrait être votre point de départ:

http://symfony.com/doc/current/book/security.html

43
Cerad

Bien qu'il soit très déconseillé d'obtenir des services dans des entités, il y a une belle façon de le faire qui n'implique pas de jouer avec le noyau global.

Les entités de doctrine ont des événements de cycle de vie auxquels vous pouvez accrocher un écouteur d'événements, voir http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-events Pour les besoins de l'exemple, je vais utiliser postLoad, qui se déclenche peu de temps après la création de l'entité.

Les EventListeners peuvent être créés en tant que services dans lesquels vous injectez d'autres services.

Ajoutez à app/config/config.yml:

services:
     example.listener:
           class: Alef\UserBundle\EventListener\ExampleListener
     arguments:
           - '@alef.role_service'
     tags:
           - { name: doctrine.event_listener, event: postLoad }

Ajoutez à votre entité:

 use Alef\UserBundle\Service\RoleService;

 private $roleService;

 public function setRoleService(RoleService $roleService) {
      $this->roleService = $roleService;
 }

Et ajoutez le nouvel EventListener:

namespace Alef\UserBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Alef\UserBundle\Service\RoleService;

class ExampleListener
{
     private $roleService;

     public function __construct(RoleService $roleService) {
         $this->roleService = $roleService;
     }

     public function postLoad(LifecycleEventArgs $args)
     {
         $entity = $args->getEntity();
         if(method_exists($entity, 'setRoleService')) {
             $entity->setRoleService($this->roleService);
         }
     }
}
22
Kai