shuba.ivan
shuba.ivan

Reputation: 4061

Symfony Event Listener - populate entity

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 ?

Upvotes: 3

Views: 1477

Answers (2)

Andras
Andras

Reputation: 171

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

Upvotes: 0

hasumedic
hasumedic

Reputation: 2167

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

Upvotes: 0

Related Questions