我想在更新实体时触发事件,即使数据没有改变。那么,我应该使用什么事件?
提醒:我想访问实体数据,因此我无法使用onFlush
。此外,由于实体数据未被更改,因此不会触发preUpate
或postUpdate
。
答案 0 :(得分:0)
您可以在服务管理器中集中实体的持久性。 在这位经理中尝试派遣一般事件
use Symfony\Component\EventDispatcher\GenericEvent;
...
...
public function persistAndFlush($entity)
{
$this->em->persist($entity);
$this->em->flush();
//dispatch an event
$event = new GenericEvent($entity, array('course_history' => 1));
$this->dispatcher->dispatch(YourClassEvents::UPDATE_ENTITY, $event);
}
然后你可以创建一个列表器来监听这个通用事件
更多详情
假设我们有实体产品
namespace Domain\YourBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Product
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string $productName
*
* @ORM\Column(name="productName", type="string", length=255, nullable=false)
*/
private $productName;
...
...
...
//setters and getters
}
service.xml中
<service id="yourdomain.product_manager" class="Domain\YourBundle\Service\ProductManager">
<argument type="service" id="doctrine.orm.entity_manager"/>
<argument type="service" id="event_dispatcher"/>
</service>
ProductManager类
namespace Domain\YourBundle\Manager;
use Doctrine\ORM\EntityManager;
use Domain\YourBundle\Entity\Product;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
class ProductManager
{
/**
* @var EntityManager
*/
protected $em;
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
/**
* @param EntityManager $em
*/
public function __construct(EntityManager $em, EventDispatcherInterface $dispatcher)
{
$this->em = $em;
$this->dispatcher = $dispatcher;
}
public function persistAndFlush($product)
{
$this->em->persist($product);
$this->em->flush();
//The entity is updated then dispatch an event
$event = new GenericEvent($product, array('product_name' => 1));
$this->dispatcher->dispatch('product', $event);
}
}
在service.xml中添加listener的定义
<service id="yourdomain.event.update_product" class="Domain\YourBundle\EventListener\UpdateProductListener">
<argument type="service" id="logger"/>
<tag name="kernel.event_listener" event="product" method="onUpdateProduct"/>
</service>
类UpdateProductListener
namespace Domain\YourBundle\EventListener;
use Symfony\Component\EventDispatcher\GenericEvent;
use Domain\YourBundle\Entity\Product;
use Psr\Log\LoggerInterface;
class UpdateProductListener
{
private $logger;
/**
* @param LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
/**
* Listen the generic event dispatched when the product name is updated
*
* @param GenericEvent $event
*
* @throws RuntimeException
* @throws \ErrorException
*/
public function onUpdateProduct(GenericEvent $event)
{
if ($event->getSubject() instanceof Product) {
$product = $event->getSubject();
if ($event->hasArgument('product_name') && $event->getArgument('product_name') == 1) {
/*
Make your logic (send mail, add log, notification....)
*/
$this->logger->notice('UpdateProductListener : event update product is occured');
} else {
$this->logger->notice('UpdateProductListener : event other than update product is occured.');
}
}
}
}
答案 1 :(得分:0)
我在这里看到了问题。您希望在更新后访问实体,但实体不是真正的更新。所以你显然在这里使用DQL查询,正如你正确提到的this disallows you to access pre\postUpdate。问题是,学说并不真正知道对象已被更改 - 查询可能有点复杂,因此可以隐藏对象标识符。甚至不知道(在MySQL的情况下)
某些RDBM具有RETURNING
子句,允许您查看更新结果,但它不是DB摘要,因此无法从开箱即用的DQL访问。
您可以使用本机SQL查询或执行其他技巧来获取更新的行。
如果查询不是性能关键,我宁愿建议用一些软件(php-side)处理简单的doctrine flush。
如果是 - 我认为这是不可能的。如果您对用例提供更多详细信息,可以讨论解决方法。
即。您可以使用versioning迭代EM处缓存的所有实体,并检查vesrion是否已更改。