3
votes

Who can give example? I have the entities Project and Event - Many Event to one Project, so when status project changes to 'closed_by_client', I need to create an Event for this project.

In the controller:

$project = $this
    ->getDoctrine()
    ->getManager()
    ->getRepository('ArtelProfileBundle:Project')
    ->find($id);

        $project->setCurrentStatus('closed_by_client');
        $manager->persist($project);
        $manager->flush();

Project entity:

/**
 * 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)
        ;
    }
}

I think that I could maybe do something like this, but entity Event not flush in DB:

/**
 * @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)
        ;
    }
}

I add

    /**
 * @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();
    }
}

but when flush entity have error

`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`

How to create listener for event - entity Project change status for 'closed_by_client' - create entity Event?

I did not create early event, how to create event for this business logic ?

2
You are mixing business logic with the database layer. Creating events like user [x] closed a project is actually not the job of doctrine, but of your application. You should actually create separate business logic classes who are responsible for persisting data to your entities, which should not depend on which database your are using. You could create dao's for this. Then register an event listener in symfony, which will execute some code when the onUserClosedProject-event is called. You can pass the user and the event to that function. - giorgio
I did not create early event, how to create event for this business logic ? - shuba.ivan
update my question - shuba.ivan

2 Answers

0
votes

Take into account that the prePersist and preFlush methods are within the Project class itself. In order to add it to your event's object you only need to use $this:

public function PrePersist(){
    if($this->getCurrentStatus() == self::STATE_TO_BE_INDEXED_IN_ELA_CLOSED_BY_CLIENT){
        $event = new CodeEvents();
        $event->setProject($this);
    }
}
0
votes

In the title you asking about Symfony event listeners, but you actually using doctrine event listeners.

My notes here:

1, You will need to create a symfony2 event and fire that from your doctrine events. If you want to fire symfony2 events complicates the thing a bit, as you will need access to the framework event dispatcher, you will need to inject it to your LifeCycleEventListener. So:

2, I would consider checking if the status field changed at all, otherwise you will create a lot of CodeEvent() instances when any other property changes of the Project entity and the status is already 'closed_by_client' See here: http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-callbacks-event-argument