dimanche 18 novembre 2018

Doctrine2 - Is it wrong to use event listeners for entity status change?

A question about design patterns.

I´m using doctrine2 for a project that has an entity which has a status, lets call it "entityWithStatus". When that entity changes it´s status I want other objects to be able to listening to that change and in this case create new logPost. I read the documentation about event listeners, and it feels like just the thing I need, BUT, then when I wanted to persist a new entity in the listener it did not work. The listener code runs, but the data is not persisted in the entity, the error messages says "no parameters were bound" even though all data has been set. I added a "hacky"-solution by telling the unit of work that changes have been made. I have read threads with simular problems here on Stack overflow, but none of them the awsers the question if this is the right thing to do. I watched Marco Pivetta talk about best pratices in Doctrine, and he says that "avoid lifecycle callbacks" and that realy confuses me. I see event listeners as subscribes in publish/subscribe pattern, but maybe I´m wrong?

My question is, am I missing something? should this logic be in another layer? We are using the repository/service pattern in this project. Maybe I should add subscribers in the repository and then add a "setStatus()" method that triggers the subscribers when called?

Example code:

/**
 * @Entity
 * @EntityListeners({"myEventListener"})
 * @Table(name="entityWithStatus")
 * @HasLifecycleCallbacks
 */
class entityWithStatus {
    /** @Id
     *  @Column(type="integer")
     *  @GeneratedValue
     *  @var int
     **/
    public $id;

    /**
     * @Column(type="integer", length=11)
     * @var int
     **/
    public $status;
}

logPost entity example.

/**
 * @Entity
 * @Table(name="logPosts")
 */
class logPost {
    // logPost entity
}

The event listener creates a new logPost every time the "entityWithStatus" changes status.

class myEventListener {
    public function preFlush(entityWithStatus $entityWithStatus, PreFlushEventArgs $event) {
        $log = new logPost();
        $log->setText('Status changed: ' . $entityWithStatus->getStatus());
        $entityManager = $event->getEntityManager();
        $entityManager->persist($log);

        // Hacky solution to tell unit of work about the changes
        $metaData = $entityManager->getClassMetadata('logPost');
        $entityManager->getUnitOfWork()->computeChangeSet($metaData, $trustcruitModel);
    }
}

Aucun commentaire:

Enregistrer un commentaire