Php Symfony 2.0在实体内获取服务

Php Symfony 2.0在实体内获取服务,php,service,symfony,doctrine-orm,entity,Php,Service,Symfony,Doctrine Orm,Entity,我正在仔细研究,找不到答案。 我的应用程序中有数据库角色模型。用户可以有一个角色,但该角色必须存储到数据库中 但用户需要从数据库中添加默认角色。所以我创建了一个服务: <?php namespace Alef\UserBundle\Service; use Alef\UserBundle\Entity\Role; /** * Description of RoleService * * @author oracle */ class RoleService { co

我正在仔细研究,找不到答案。 我的应用程序中有数据库角色模型。用户可以有一个角色,但该角色必须存储到数据库中

但用户需要从数据库中添加默认角色。所以我创建了一个服务:

<?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));
    }

}
现在我想在两个地方使用它:
UserController
User
实体。我怎样才能把它们放在实体内? 至于控制器,我想我只需要:

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

但如何在实体内部获得服务呢?

您没有。这是一个非常常见的问题。实体应该只知道其他实体,而不知道实体管理器或其他高级服务。向这种开发方式过渡可能有点困难,但通常是值得的

您要做的是在加载用户时加载角色。通常情况下,您最终会得到一个用户提供者来完成这类工作。你看过关于安全的章节了吗?这应该是你的出发点:


首先,将服务引入实体如此困难的原因是,Symfony的明确设计意图是永远不要在实体内部使用服务。因此,最佳实践答案是重新设计应用程序,使其不需要在实体中使用服务

然而,我发现有一种方法可以做到这一点,它不涉及全局内核

条令实体有生命周期事件,您可以将事件侦听器挂接到这些事件,为了示例起见,我将使用postLoad,它会在实体创建后立即触发

EventListener可以作为服务创建,您可以将其他服务注入其中

添加到app/config/config.yml:

services:
     example.listener:
           class: Alef\UserBundle\EventListener\ExampleListener
     arguments:
           - '@alef.role_service'
     tags:
           - { name: doctrine.event_listener, event: postLoad }
向您的实体添加:

 use Alef\UserBundle\Service\RoleService;

 private $roleService;

 public function setRoleService(RoleService $roleService) {
      $this->roleService = $roleService;
 }
并添加新的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);
         }
     }
}

请记住,这个解决方案有一个警告:这仍然是一种快速而肮脏的方法,而且你确实应该考虑重新设计你的应用程序。我讨厌“你不能”、“这是一个错误的设计模式”或“它会毁掉一切,你这个白痴!”之类的答案,这些答案都是虚无缥缈的大师写的。“更糟(有时)更好”;)再次感谢。遗憾的是,“错误的设计模式”、“MCV模式”、“分离业务层”等等。。当“老板”想要“马上”完成事情时,就从窗口出去。谢谢你的回答@Kai,这就是我一直在寻找的答案。我不喜欢在
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);
         }
     }
}