Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How exactly do I create a custom EntityManager in Symfony2/Doctrine?

New guy at Symfony/Doctrine. So kindly guide me.

Requirement: To create a custom EntityManager which would override some of the methods like remove (instead of remove, i want to perform an update and modify a parameter like isValid in my class, so that the records are never deleted) and a find ( find a record which has a non zero isValid ) etc and use it instead of Doctrine's EntityManager.

I started reading through this thread: Is there a way to specify Doctrine2 Entitymanager implementation class in Symfony2? and found the answer by user2563451 to be not so straightforward. I got lost when he talks about not to follow certain approaches (again no location of the files to be modified).

I have looked at the EntityManager.php and it specifically tells not to use extend the EntityManager class. Rather it asks to extend the EntityManagerDecorator. On looking at the EntityManagerDecorator, there are no methods available inside it (like create, persist, etc which I found in EntityManager) Does it mean I need to create new methods for each and every single Entity Manager functionality ?

Since there is no clear defined way to get this done, I am confused to get this thing started. Also Doctrine cookbook is of little use to me as it does not have any information to achieve this.

So any help regarding the extending of EntityManagerDecorator or EntityManager is appreciated.

Best if you can provide me step by step directions to achieve the same.

Thanks !

Edit 1: my requirement is to use my custom EntityManager instead of Doctrine's EntityManager (EM) and modify those 'remove' and 'find' methods as per my requirements. I am not sure whether I need to reuse the functionality provided by Doctrine's EM or write from scratch.

like image 400
VKB Avatar asked Aug 07 '15 19:08

VKB


People also ask

How should be the process to add a new entity to the app in Symfony?

With the doctrine:database:create command we create a new database from the provided URL. With the make entity command, we create a new entity called City . The command creates two files: src/Entity/City. php and src/Repository/CityRepository.

Why is EntityManager closed?

The EntityManager becomes closed as soon as an SQL exception is thrown by the underlying connection. The "real" exception has surely occurred before that. You will need a new EntityManager.

What is doctrine repository?

A repository in a term used by many ORMs (Object Relational Mappers), doctrine is just one of these. It means the place where our data can be accessed from, a repository of data. This is to distinguish it from a database as a repository does not care how its data is stored.


1 Answers

I think you may be confusing a Manager with a Repository.

An EntityManager is really nothing more than a Service you use to manage that specific or a collection of entities.

A repository extends \Doctrine\ORM\EntityRepository and is what tells Doctrine how to store your entity in the database.

You can use the combination of these two to achieve what you want.

For example. Let's take our entity Foo

class Foo
{
    //...other properties

    protected $isValid;

    //...Getters and setters
}

We then have a manager for Foo.

class FooManager
{
    protected $class;
    protected $orm;
    protected $repo;

    public function __construct(ObjectManager $orm , $class)
    {
        $this->orm = $orm;
        $this->repo = $orm->getRepository($class);

        $metaData = $orm->getClassMetadata($class);
        $this->class = $metaData->getName();
    }

    public function create()
    {
        $class = $this->getClass();
        $foo = new $class;

        return $foo;
    }

    public function findBy(array $criteria)
    {
        return $this->repo->findOneBy($criteria);
    }

    public function refreshFoo(Foo $foo)
    {
        $this->orm->refresh($foo);
    }

    public function updateFoo(Foo $foo, $flush = true)
    {   
        $this->orm->persist($foo);
        if($flush)
        {
            $this->orm->flush();
        }
    }

    public function getClass()
    {
        return $this->class;
    }
}

We have some basic functions for Creating and Updating our object. And now if you wanted to "remove" it without actually deleting it, you can add the following function in the Manager.

public function remove(Foo $foo)
{
    $foo->setIsValid(false);
    return $this->update($foo);
}

This way, we update the isValid fields to false and persist it to the database. And you'd use this like any service inside your controller.

class MyController extends Controller
{
    public function someAction()
    {
        $fooManager = $this->get('my_foo_manager');
        $newFoo = $fooManager->create();

        //...
        $fooManager->remove($newFoo);
    }
}

So now we've got the remove part.

Next, we only want to find entities that isValid set to TRUE.

Honestly, the way I'd handle this is not even modify the find and instead in your controller

if(!$foo->getIsValid())
{
    //Throw some kind of error.  Or redirect to an error page.
}

But if you want to do it the other way. You can just make a repo.

use Doctrine\ORM\EntityRepository;
class FooRepository extends EntityRepository
{
    public function find($id, $lockMode = LockMode::NONE, $lockVersion = null)
    {
        //Some custom doctrine query.
    }
}

We override EntityRepository's native find() function with our own.

Finally we get all of this registered in the right places. For the manager you've got to make a service.

services:
    my_foo_manager:
        class: AppBundle\Manager\FooManager
        arguments: [ "@doctrine.orm.entity_manager" , 'AppBundle\Entity\Foo']

And for the repository, you must specify the repositoryClass in the ORM definition of your entity.

AppBundle\Entity\Foo:
    type: entity
    repositoryClass: AppBundle\Entity\FooRepository
    table: foos
    id:
        id:
            type: integer
            generator: {strategy: AUTO}
            options: {unsigned: true}
    fields:
        isValid:
            type: boolean

Knowing all of this you can now do some pretty cool things with Entities. I hope this helped. Good luck!

like image 69
Squeegy Avatar answered Oct 04 '22 21:10

Squeegy