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?
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.
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.
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.
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.
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/
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With