Edd*_*die -1 php symfony entitylisteners doctrine-orm
在Doctrine 2.4之前,捕获生命周期事件(例如prePersist)的默认方式是为所有实体触发的全局事件侦听器.运行像Symfony服务这样的监听器可以很容易地注入其他服务(如request或request_stack对象).
现在,更好的解决方案似乎是一个实体监听器,因为它带来的开销更少!
那么让我们在实体标题中开始这个...:
* @ORM\EntityListeners({ "AppBundle\Entity\Listener\LanguageListener" })
Run Code Online (Sandbox Code Playgroud)
这是班级:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我对如何访问Symfonys服务(在这种情况下是request对象)没有任何想法.
可是等等!有一种方法:
global $kernel;
if ('AppCache' == get_class($kernel))
{
$kernel = $kernel->getKernel();
}
$request = $kernel->getContainer()->get('request');
Run Code Online (Sandbox Code Playgroud)
而且它也在发挥作用.
但在我的所有研究中,我发现很多相关的问题都严格警告了!唯一的区别:所有这些问题都是指实体,而不是实体听众 ......
......引导我到这两个问题:
[编辑:]再次(见第一句)让我说清楚这个问题也是关于如何不使用服务.服务需要一定的费用,请参阅昂贵的服务建设.特别是在这种情况下,我很少需要这些功能 - 这就是我想要使用不作为服务运行的实体监听器的原因.
对不起,我并没有过分强调这一方面.不知道为什么这有资格降低率...
[编辑2:]为了让事情更清楚,我又添加了一个代码示例(第一个),展示了事物的映射方式.
从doctrine/doctrine-bundle >= 1.5.0实体开始,可以将侦听器创建为服务,如果它们被标记,则doctrine.orm.entity_listener它们将自动注册到所需的实体管理器中.您可以将所需的依赖项注入服务,例如请求堆栈.
创建一个监听器:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
将其注册为服务:
app.doctrine.language_listener:
class: AppBundle\Doctrine\Listener\LanguageListener
public: false
arguments: ["@request_stack"]
tags:
- { name: "doctrine.orm.entity_listener" }
Run Code Online (Sandbox Code Playgroud)
注释实体:
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
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
请注意,以这种方式注册的实体侦听器不会延迟加载,因此在创建实体管理器时将创建它们及其依赖项.
更新:
所以如果你的问题是关于如何懒惰地使用它.我想到的第一个解决方案是将它声明为一个惰性服务,但是在这种情况下它实际上并没有按预期工作,因为在注释中我们使用了一个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 }
Run Code Online (Sandbox Code Playgroud)
这样您就可以使用惰性服务,但它只适用于doctrine/orm >= 2.5.0.
另一个解决方案是创建一个自己的实体监听器解析器,它知道容器(这实际上不是一件好事)并在需要时使用它来获取监听器.有一篇博客文章介绍了一种方法.
| 归档时间: |
|
| 查看次数: |
2565 次 |
| 最近记录: |