Silex + Doctrine ORM doesn't fire events when set on @MappedSuperclass

584 views Asked by At

I am using Silex with Doctrine ORM, everything was working properly but I got a problem that I can't figure out.

I have an Entity News in the namespace Lpdq\Model\Entity which extends another class News in the namespace Lpdq\Model which contains some methods and pre/post event methods for doctrine.

My entity News

<?php

namespace Lpdq\Model\Entity;

/**
 * News
 * 
 * @Table(name="news")
 * @Entity(repositoryClass="Lpdq\Model\Entity\Repository\News")
*/
class News extends Lpdq\Model\News{
 /*some properties/methods*/
}

My super class News

<?php

namespace Lpdq\Model;
/**
 * News
 * 
 * @MappedSuperclass
 * @HasLifecycleCallbacks
*/
class News{

   /**
    * @PrePersist
    */
    public function prePersist()
    {
        $this->setCreated(new \DateTime());
        $this->setUpdated(new \DateTime());
    }

    /**
     * @PreUpdate
     */
    public function preUpdate()
    {
        $this->setUpdated(new \DateTime());
    }

    /*...some methods...*/
}

In my controller, I just instance my entity and persist/flush it

<?php

namespace Lpdq\Controller;

use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Lpdq\Model\Entity\News;

class NewsController {

    public function addAction( Request $request, Application $app) {
        $news = new News();
        $news->setTitle('test');
        /*...*/
        $app['orm.em']->persist($news);
        $app['orm.em']->flush();

        /*...*/
    }
}

My problem is that my prePersist/preUpdate methods are not called when I persist my entity. (So I get an error because my properties created and updated are null)

If I set my entity News as HasLifecycleCallbacks and put the same prePersist/Update method, they are triggered.

While I am here, I am wondering if the way I extends my entities to put pre/post and other methods are a good or bad practice?

2

There are 2 answers

0
abhinavlal On

If you have multiple entities which need same set of methods then having a base class news makes sense, if only one entity is extending the class news then it's a overkill and you can put the code in your entity class itself.

The general pattern is if you have multiple entities and all for them have created and updated field then you should create a base class and all such entities should extend it.

You need to have the annotation HasLifecycleCallbacks to enable Lifecycle callbacks. If the lifecycle events are applicable for all entities you are extending from base class then you should put in the annotation in base class otherwise put it in individual classes.

0
andig On

You have Lpdq\Model\Entity\News extending Lpdq\Model\News which is at least confusing. You're also only showing partial implementation- make sure that setTitle() actually updates tracked model properties for Doctrine to identify the instance as dirty. Otherwise the flush events won't be called.