Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何惰性地创建实体侦听器并向其中注入依赖项_Php_Symfony_Doctrine Orm_Entitylisteners - Fatal编程技术网

Php 如何惰性地创建实体侦听器并向其中注入依赖项

Php 如何惰性地创建实体侦听器并向其中注入依赖项,php,symfony,doctrine-orm,entitylisteners,Php,Symfony,Doctrine Orm,Entitylisteners,在条令2.4之前,捕获生命周期事件的默认方法(如prePersist)是一个全局,它将为所有实体触发。将这样的侦听器作为Symfony服务运行可以轻松地注入其他服务(如request或request\u堆栈对象) 现在更好的解决方案似乎是,因为这样会大大减少开销 让我们从实体标题开始…: * @ORM\EntityListeners({ "AppBundle\Entity\Listener\LanguageListener" }) 下面是课程: namespace AppBundle\Enti

在条令2.4之前,捕获生命周期事件的默认方法(如
prePersist
)是一个全局,它将为所有实体触发。将这样的侦听器作为Symfony服务运行可以轻松地注入其他服务(如
request
request\u堆栈
对象)

现在更好的解决方案似乎是,因为这样会大大减少开销

让我们从实体标题开始…:

* @ORM\EntityListeners({ "AppBundle\Entity\Listener\LanguageListener" })
下面是课程:

namespace AppBundle\Entity\Listener;

use Doctrine\ORM\Event\LifecycleEventArgs;

class LanguageListener
{
    public function prePersist($obj_entity, LifecycleEventArgs $obj_eventArgs)
    {    
        $request = ???;

        // set entity to users preferred language (for example 'de')
        $obj_entity->setLanguage($request->getLocale());
    }
}
如您所见,我一点也不知道如何访问Symfonys服务(在本例中为
请求
对象)

但是等等!有一种方法:

global $kernel;
if ('AppCache' == get_class($kernel))
{
    $kernel = $kernel->getKernel();
}
$request = $kernel->getContainer()->get('request');
它也在起作用

但在我所有的研究中,我发现了很多相关的问题,这些问题都是严格警告我的! 唯一的区别是:所有这些问题都是针对实体的,而不是针对实体听众的

。。。让我来回答这两个问题:

  • 上述解决方案是否可行
  • 如果没有:应该如何做

  • [编辑:再次(见第一句话)让我澄清一下,这个问题也是关于如何使用服务的。服务是有成本的,请参阅。特别是在这种情况下,我很少需要该功能——这就是为什么我希望使用不作为服务运行的实体侦听器

    对不起,我没有过分强调这一方面。不知道为什么这有资格降低利率


    [Edit2::为了让事情更清楚,我又添加了一个代码示例(第一个)这显示了事物是如何映射的。

    条令/条令包>=1.5.0
    实体侦听器可以创建为服务,如果它们被标记为
    条令.orm.entity\u侦听器
    ,它们将自动注册到。您可以将所需的依赖项注入服务,例如请求堆栈

    创建侦听器:

    namespace AppBundle\Doctrine\Listener;
    
    use Symfony\Component\HttpFoundation\RequestStack;
    
    class LanguageListener
    {
        /**
         * @var RequestStack
         */
        private $requestStack;
    
        public function __construct(RequestStack $requestStack)
        {
            $this->requestStack = $requestStack;
        }
    
        public function prePersist($entity)
        {
            if (null !== $request = $this->requestStack->getCurrentRequest()) {
                // put the logic here
            }
        }
    }
    
    将其注册为服务:

    app.doctrine.language_listener:
        class: AppBundle\Doctrine\Listener\LanguageListener
        public: false
        arguments: ["@request_stack"]
        tags:
            - { name: "doctrine.orm.entity_listener" }
    
    注释实体:

    namespace AppBundle\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use FOS\UserBundle\Entity\User as BaseUser;
    
    /**
     * @ORM\Entity()
     * @ORM\EntityListeners("AppBundle\Doctrine\Listener\LanguageListener")
     * @ORM\Table("user_")
     */
    class User extends BaseUser
    {
        // ...  
    }
    
    请注意以这种方式注册的实体侦听器不会延迟加载,因此在创建实体管理器时将创建它们及其依赖项

    更新:

    所以如果你的问题是关于如何懒散地使用它。我想到的第一个解决方案是将其声明为,但在本例中,它实际上没有按预期工作,因为在注释中,我们使用了一个concrate类,该类将在需要时由侦听器解析器创建,但在本例中,我们应该在注释中写入代理类名,以使用代理对象,这是不可能的。不过有一个解决方案(目前没有文档记录),不使用
    @EntityListeners
    注释实体,而是使用标记参数注册侦听器。大概是这样的:

    app.doctrine.language_listener:
        class: AppBundle\Doctrine\Listener\LanguageListener
        arguments: ["@request_stack"]
        lazy: true
        tags:
            - { name: "doctrine.orm.entity_listener", entity: AppBundle\Entity\User, event: preUpdate }
            - { name: "doctrine.orm.entity_listener", entity: AppBundle\Entity\User, event: postUpdate }
    
    通过这种方式,您可以使用惰性服务,但它仅适用于
    原则/orm>=2.5.0


    另一个解决方案是了解容器(这实际上不是一件好事),并在需要时使用它获取侦听器。有一种方法可以做到这一点。

    您已经看到了吗?我认为这是与symfony方法结合使用的解决方案,我还没有真正掌握解析器的概念。今天早些时候读到过,好书:但无论如何,这仍然不能解决我的问题。据我所知,让服务接受容器作为参数被认为是不好的做法。你应该通过你需要的服务@Matteo的方法是Eddie应该做的,以使事情顺利进行。谢谢你简洁的回答!但这并不是我问题的答案:我很清楚我可以使用一个服务并注入一切(以及它是如何完成的)。但这正是我想要避免的。看到新的编辑和我在原始问题中的第一句话,我真的不明白你想在这里实现什么。这是一个监听用户实体事件的实体侦听器。应该这样做。如果您不想手动实例化它,那么您必须执行与容器现在所做的相同的操作。您必须尽快将其注册到实体管理器中,以捕获所需的事件。您可以尝试将其定义为代理,以便创建代理(但这需要“symfony/proxy-manager桥”)或创建工厂。我看到我的上述解决方案正在工作:仅在需要时加载和调用它。既然这是教义,就不能完全错,对吧?唯一的问题是如何以正确的方式访问
    请求
    服务。听起来很有希望!“好吧,我看到我上面的解决方案正在工作:它只在需要时加载和调用”。。。那不是真的。。。如何将侦听器注册到EM中?每一个请求你都必须这样做。顺便说一句,您应该记住,这种方法只适用于web环境,而不适用于控制台命令,因为那里没有请求。