До 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');
И это тоже работает.
Но во всех моих исследованиях я обнаружил множество связанных вопросов, строго предупреждающих об этом!
Единственная разница: все эти вопросы касались юридические лица, не для Слушатели сущности…
… приводит меня к этим двум вопросам:
[Редактировать:] Еще раз (см. Первое предложение) позвольте мне прояснить, что этот вопрос также о том, как не использовать сервис. Услуги предоставляются за определенную плату, см. Дорогой Сервис Строительство. И особенно в этом случае мне редко нужны функциональные возможности — поэтому я хочу использовать Entity Listeners, которые делают не запустить как службу.
Извините, я не слишком подчеркивал этот аспект. Не уверен, почему это может привести к снижению ставки, хотя …
[Edit2:] Чтобы прояснить ситуацию, я добавил еще один пример кода (первый), который показывает, как все отображается.
По состоянию на 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сть Сообщение блога о способе сделать это.
Других решений пока нет …