谁能举个例子?我有一个项目Project
和Event
- 多个事件的实体,所以当状态项目更改为'closed_by_client'
时,我需要为此项目创建一个事件。
在控制器中:
$project = $this
->getDoctrine()
->getManager()
->getRepository('ArtelProfileBundle:Project')
->find($id);
$project->setCurrentStatus('closed_by_client');
$manager->persist($project);
$manager->flush();
项目实体:
/**
* Project.
*
* @ORM'Table(name="project")
* @ORM'HasLifecycleCallbacks
* @Gedmo'SoftDeleteable(fieldName="deletedAt")
* @ORM'Entity(repositoryClass="Artel'ProfileBundle'Entity'Repository'ProjectRepository")
* @ExclusionPolicy("all")
*/
class Project
{
const STATE_TO_BE_INDEXED_IN_ELA_NOT_APPROVED = 'not_approved';
const STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT = 'closed_by_client';
use Timestampable;
/**
* @var int
*
* @ORM'Column(name="id", type="integer")
* @ORM'Id
* @Expose()
* @ORM'GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM'Column(name="current_status", type="string", length=100, nullable = true)
* @Expose()
* @Type("string")
*/
protected $currentStatus = 'not_approved';
/**
* @ORM'OneToMany(targetEntity="CodeEvents", mappedBy="project", cascade={"persist", "remove"})
*/
protected $events;
/**
* @ORM'PrePersist()
*/
public function PrePersist(){
if($this->getCurrentStatus() == self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT){
$event = new CodeEvents();
$event
->setProject($this)
->setEvent(self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT)
;
}
}
/**
* @ORM'PreFlush()
*/
public function PreFlush(){
if($this->getCurrentStatus() == self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT){
$event = new CodeEvents();
$event
->setProject($this)
->setEvent(self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT)
;
}
}
我认为我也许可以做这样的事情,但实体Event
不会在数据库中刷新:
/**
* @ORM'PrePersist()
*/
public function PrePersist(){
if($this->getCurrentStatus() == self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT){
$event = new CodeEvents();
$event
->setProject($this)
->setEvent(self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT)
;
}
}
/**
* @ORM'PreFlush()
*/
public function PreFlush(){
if($this->getCurrentStatus() == self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT){
$event = new CodeEvents();
$event
->setProject($this)
->setEvent(self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT)
;
}
}
我加
/**
* @ORM'PreFlush()
*/
public function PreFlush(LifecycleEventArgs $event){
$entityManager = $event->getEntityManager();
if($this->getCurrentStatus() == self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT){
$event = new CodeEvents();
$event
->setProject($this)
->setEvent(self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT)
;
$entityManager->persist($event);
$entityManager->flush();
}
}
但是当刷新实体有错误时
`Catchable Fatal Error: Argument 1 passed to Proxies'__CG__'Artel'ProfileBundle'Entity'Project::PreFlush() must be an instance of Doctrine'ORM'Event'LifecycleEventArgs, instance of Doctrine'ORM'Event'PreFlushEventArgs given, called in /home/ivan/host/aog-code/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php on line 102 and defined`
如何为事件创建侦听器 - 实体 "closed_by_client"的项目更改状态 - 创建实体事件?
我没有创建早期事件,如何为此业务逻辑创建事件?
考虑到 prePersist 和 preFlush 方法位于 Project 类本身中。为了将其添加到事件的对象中,您只需要使用$this
:
public function PrePersist(){
if($this->getCurrentStatus() == self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT){
$event = new CodeEvents();
$event->setProject($this);
}
}
在标题中,你询问了Symfony事件监听器,但实际上你使用了doctrine事件监听器。
我的笔记在这里:
1,你需要创建一个symfony2事件,并从你的教义事件中触发它。如果你想触发symfony2事件会使事情变得有点复杂,因为你需要访问框架事件调度器,你需要把它注入到你的LifeCycleEventListener。所以:
- 为此状态更改创建您自己的Symfony事件http://symfony.com/doc/current/components/event_dispatcher/introduction.html#creating-and-dispatching-an-event
- 为您的项目实体创建一个单独的 Doctrine 实体事件侦听器,您可以在其中注入 SF 框架事件调度程序
- 在 SF2 配置中定义它http://symfony.com/doc/current/bundles/DoctrineBundle/entity-listeners.html
- 在 Doctrine 侦听器中使用事件调度程序 调度状态更改事件
- 在Symfony中创建您的事件订阅者或侦听器,它将处理状态更改事件(与第一个点的链接相同)。
2,我会考虑检查状态字段是否发生了变化,否则当项目实体的任何其他属性更改并且状态已经为"closed_by_client"时,您将创建大量CodeEvent()实例看这里:http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-callbacks-event-argument