Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 entityManager in model

I'm going to use entity_manager in my model. But entity_manager is only available in controller: throw $em = $this->get('doctrine.orm.entity_manager'). So, I have to define model methods with $em parameter. This is making phpUnit testing pretty difficult and violates application structure. For example:

class Settings
{
    public static function getParam( $em, $key )
    {
        $em->createQuery("
            SELECT s
            FROM FrontendBundle:Settings s
            WHERE s.param = {$key}
        ");
        return $em->getResult();
    }
}

Is there any approach to use entity_manager service in model section?

like image 539
Aleksei Kornushkin Avatar asked Feb 10 '11 04:02

Aleksei Kornushkin


People also ask

What is Entity manager in Doctrine?

Doctrine's public interface is through the EntityManager . This class provides access points to the complete lifecycle management for your entities, and transforms entities from and back to persistence. You have to configure and create it to use your entities with Doctrine ORM.

How Doctrine works?

Doctrine uses the Identity Map pattern to track objects. Whenever you fetch an object from the database, Doctrine will keep a reference to this object inside its UnitOfWork. The array holding all the entity references is two-levels deep and has the keys root entity name and id.

What is Doctrine db?

The Doctrine Project is the home to several PHP libraries primarily focused on database storage and object mapping. The core projects are the Object Relational Mapper (ORM) and the Database Abstraction Layer (DBAL) it is built upon.

Why is EntityManager closed?

This is how I solved the Doctrine "The EntityManager is closed." issue. Basically each time there's an exception (i.e. duplicate key) or not providing data for a mandatory column will cause Doctrine to close the Entity Manager.


2 Answers

First, a starting note: by convention your Entity class should probably be singular. So, Setting, not Settings. You could argue that "settings" as a group of related settings could be seen as one entity. Still, something to bear in mind.

In Doctrine2, you would use a repository to make this type of query. In your code where you were going to call Settings::getParam, you would instead fetch the repository and query that. In symfony2, say:

// $em is your entitymanager, as you were going to pass to your method above
// $key is the key you were going to pass to your method above
$repository = $em->getRepository('\FrontendBundle\Settings');
$setting = $repository->getByParam($key);

By default, without writing any code, repositories define getByXXXX for each field in your entity.

If you have a more complicated query to make, you can extend the repository.

use Doctrine\ORM\EntityRepository;

class SettingsRepository extends EntityRepository 
{
    public function getBySomeComplicatedQuery() {
        $sort_order = $this->getEntityManager()
            ->createQuery('SELECT count(s) FROM FrontendBundle\Settings s WHERE s.value > 32')
            ->getResult(Query::HYDRATE_SINGLE_SCALAR);
    }

}

And then you'd call that method in the same way.

Others would advocate the use of a Manager object which would then not be tied to the Entity/ORM, but that's a needless complication in this case I think.

Doctrine2 is specifically designed to not let you use queries in your Entity file; Entities and EntityManagers are actually two aspects of the standard model layer, split apart to enforce best practices. See this article: http://symfony2basics.jkw.co.nz/get-symfony2-working/entities/

like image 131
Jeremy Warne Avatar answered Dec 03 '22 12:12

Jeremy Warne


Queries in the Entity class

Putting queries in you entity seems odd to me. The same way as putting queries into your model class in Doctrine 1 it is not considered a good practice. Entity classes should be light.

I'm actually learning Doctrine2 and was thinking about similar problem: where to put queries?

In Doctrine 1 there are special Table classes and I was expecting something similar in Doctrine 2.

Repository Pattern

Today I learned that Doctrine 2 is using the Repository Pattern: http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html#custom-repositories

However, to retrieve an instance of repository class you need to use Entity Manager. One way or another you need it.

Still, following the repository pattern seems a better choice.

In my opinion If you insist on having query method in your Entity class you have to pass an Entity Manager to it.

Testing

Why the need of passing entity manager makes it hard to test? From my experience explicit dependencies make testing easier as you can control them in the test (and mock them for example).

On the other hand passing the entity manager to every method is not right choice either. In such case I'd make the dependency obligatory and add it to the contructor.

like image 30
Jakub Zalas Avatar answered Dec 03 '22 12:12

Jakub Zalas