3

I'm working on a Symfony2/Doctrine2 project which handles 2 databases on MSSqlServer.

The first database A_db has a table forms and the second one B_db has people. All my entities are defined with annotations.

I need to get all forms from forms related to people as I will explain in following lines.

I've spent some time reading related answered questions:

So I decided that a service might be the best way to handle my needs. But it makes no clear to me how actually get this done. I mean, where to put my service class, how to define it in config.yml, how into people entity...

My wish is to set up a full service (assuming its the best implementation) to perform something like:

foreach($onePeple->getForms() as $form) {/* some code with form */}

In case service implementation for doctrine is not the best practice, then what would it be and how can I make it work?

Community
  • 1
  • 1
Cristian Douce
  • 2,838
  • 1
  • 13
  • 17

1 Answers1

0

What you're asking there is possible using the entities alone - so long as you define a relationship such as this on the Form entity:

/**
 * @OneToMany(targetEntity="Form", mappedBy="User")
 */
protected $Forms;

And on the User entity:

/**
 * @ManyToOne(targetEntity="User", inversedBy="Forms")
 */
protected $User;

Then you can simply load a User entity (through a service, a repository or however you wish) and then access all the forms belonging to that user through $userObj->Forms (if using magic __get on your entities, if not then using a getter method, again down to your preference). Forms is an instance of an object implementing the Doctrine\Common\Collections\Collection interface (since it is a to-many relationship) which is iterable using a foreach.

In projects I have worked on using Doctrine2, we typically use our services for getting, saving and deleting entities, along with listing entities of a type (we call them index methods). This way you can tie in extra functionality required in saving, such as updating other entities which are closely associated and so on. These services are tied to the persistence layer and contain a reference to the entity manager, leaving the entities themselves isolated and testable.

We've also had the argument of whether to put this kind of logic in repositories or services, but that is more a case of personal preference and/or project requirements.

One thing to note - services you build are not going to be linked into Doctrine. It is unaware of your service layer (it's just some userland code) so it is up to you to link it in a meaningful and clean manner. Essentially you'd want something where you could pass the entity manager in through the constructor of the service and have some kind of base service class capable of operating on all entities, which could then be extended with special logic on a per-entity basis. Repositories, however, are intrinsically linked into Doctrine, so if that is what you want then it might be the best solution. We tended to use services as they are then purely related to implementing the business rules and so on, leaving the repositories to be used as a component of the persistence layer.

Geoff Adams
  • 1,114
  • 6
  • 14
  • Thanks! But I've already thought about using Association mapping with no good result. The problem here is that I'm talking of tables on different databases, which means different connections configuration and of course different entity managers. When trying to use get/set methods I get the error telling "forms Obj doesn't exist", because in that connection configuration (the one of **B_db**) table _forms_ and mapping _forms_ doesn't exist. My business with services is that I could handle both $em so I can do that tricky query to get Forms from **A_db** related to each User in **B_db**. Right? – Cristian Douce Oct 06 '11 at 17:02
  • Maybe I'm not understanding your proposition. I though association mapping through multiple databases wasn't really supported by Doctrine. This article on Doctrine's Blog: [Cross Database Joins](http://www.doctrine-project.org/blog/cross-database-joins) seems to be something that would work "fine". But as I can`t change ONE database column's names I can't even test it and then I'm back to services proposal and my first question: **How do I get Services working Symfony2 with Doctrine?**. – Cristian Douce Oct 06 '11 at 17:09
  • Well, it's a mighty conundrum you have there, complicated by the multiple databases configuration. Services aren't something you 'get working' - they're classes you create, you instantiate (like any other class), you utilise. All you need to do is pass in the entity manager and write some code within them to achieve the desired ends - using the entity manager to fetch, etc. If, in your case, you must pass in two entity managers, then that is what you must do. – Geoff Adams Oct 06 '11 at 20:25
  • Ok, now I return to my original question. How to define Services? How instantiate them? How call them inside one entity method **getForms()**? I'm a little bit confused on where to place them, configure the config.yml, etc... – Cristian Douce Oct 06 '11 at 23:09
  • You shouldn't be obtaining a service from within an entity. Think of it like this - the entity itself is a data store, with operations within the scope of the data. You might tie in validation functionality, calculation functions and so on which is related to the domain of the entity itself. Your `getForms()` method is not directly an operation on the entity - since it is accessing a different model entirely (a separate, pre-existing database), it is something on the service level. A service is something which operates *upon* or *using* entities, which is your requirement. – Geoff Adams Oct 06 '11 at 23:41
  • Doctrine itself does not have any concept of a service, simply a repository, which a different thing - think of it as the collection of entities of a single type. Therefore it is up to you to define a) the structure of your service, b) the purpose of the service (in this case, one responsibility would be to bridge the gap between distinct data models) and c) the pattern of usage of the service. I have used factory patterns to instantiate them for instance, while using a common abstract base for all services. Services utilise Doctrine, not the other way round. – Geoff Adams Oct 06 '11 at 23:46