Как лениво создавать Entity Listener и вставлять в него зависимости

До Doctrine 2.4 стандартный способ отловить события жизненного цикла (например, prePersist) был глобальным слушатель событий это будет стрелять для всех лиц. Запуск такого прослушивателя, как служба Symfony, облегчил внедрение других служб (таких как request или же request_stack объекты).

Теперь лучшим решением кажется слушатель сущностей так как это идет с намного меньшими накладными расходами!

Итак, давайте запустим эту вещь в заголовке нашей сущности …:

* @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 (в данном случае request объект).

Но ждать! Есть выход:

global $kernel;
if ('AppCache' == get_class($kernel))
{
$kernel = $kernel->getKernel();
}
$request = $kernel->getContainer()->get('request');

И это тоже работает.

Но во всех моих исследованиях я обнаружил множество связанных вопросов, строго предупреждающих об этом!
Единственная разница: все эти вопросы касались юридические лица, не для Слушатели сущности

… приводит меня к этим двум вопросам:

  1. Вышеупомянутое решение — путь?
  2. А если нет: как это сделать?

[Редактировать:] Еще раз (см. Первое предложение) позвольте мне прояснить, что этот вопрос также о том, как не использовать сервис. Услуги предоставляются за определенную плату, см. Дорогой Сервис Строительство. И особенно в этом случае мне редко нужны функциональные возможности — поэтому я хочу использовать Entity Listeners, которые делают не запустить как службу.

Извините, я не слишком подчеркивал этот аспект. Не уверен, почему это может привести к снижению ставки, хотя …

[Edit2:] Чтобы прояснить ситуацию, я добавил еще один пример кода (первый), который показывает, как все отображается.

-1

Решение

По состоянию на 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
}
}
}

Зарегистрируйте это как услугу:

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 }

Таким образом, вы можете использовать ленивые сервисы, но он работает только с doctrine/orm >= 2.5.0,

Другое решение было бы создать собственный распознаватель слушателя сущности который знает о контейнере (это на самом деле не очень хорошая вещь) и использует его, чтобы получить слушателя, когда это необходимо. Eсть Сообщение блога о способе сделать это.

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]