Reputation: 648
Yes I know, I'm not supposed to do this. But from a developers point of view, it "seems" the easiest solution in my particular case (but I'm open to better suggestions).
I have 3 entities: List, Item and Product. A List can have several Items and an Item can have several Products linked to it.
In the Twig template, the Items of the list are enumerated and for each Item, all the linked products are enumerated as well. So far so good, this is all relatively simple.
Now I would like to extend this by adding suggested products if the number of linked products is smaller than 3. These suggestions are not linked to the Item in the database, it's an ad-hoc full-text query that uses the name of the Item as a search value and returns a list of matching products. This search functionality is already available in the Repository class for the Product entity.
So I was thinking of adding a function to the Item entity named getSuggestions(). This function would then retrieve 3 products that could be matched with the Item, without actually linking them to the item. So if I had the EM available in that function, I could simple get the Repository class of the Products entity to do the full-text search by passing the Item to it. This would allow me to get the list of suggestions in the template (the only place I need them), just by calling the getSuggestions function on the Item objects as they are processed in the template.
Upvotes: 0
Views: 182
Reputation: 5567
but I'm open to better suggestions
I think the Single Responsibility Principle is a good reason to stop and rethink this. An Item
should do one thing. Keep track of its properties and relationships. It shouldn't be querying the database. It shouldn't be calculating things (usually). It should be a means of passing around properties and relationships.
In fact, it is good to keep the Entity
's decoupled, such that they are never aware that the database even exists. Keeping things testable is a big reason. But also, it means you could one day change your application to get the Entity
data from another source, like a 3rd party API or something, and all of your Entity
's and the code that relies on them is unchanged.
Now, my suggestion, is to move this logic to a new class. I'll leave the naming up to you, but this could be a class called Suggester
. And Suggester
has a method that takes an Item
and uses the EntityManager
(via dependency injection) to make the query.
It may also just be a good idea to add this method to your custom ProductRepository
. That class is responsible for querying the database for Product
s, so it is a logical place for this code. As you said "I could simple get the Repository class of the Products entity to do the full-text search by passing the Item to it."
You say that you want a property on Item
so it's easy to use in Twig. You should stop and rethink this. Your Twig template is you "view" in the MVC. The view is responsible for presenting data. When you are querying the database, you should be doing so from your model, which is called by your controller. The way I see it, you either get the suggestions in the controller and pass them into the template, or you provide the template with a service that is able to perform the query (along the lines of my Suggester
above).
Upvotes: 2
Reputation: 1503
I would go in an other way.
Use Doctrine event listener, and after loading the initial data from the DB, using the event postLoad, you can determent the amount of the linked product, and if lower then 3, you can run it there automatically. Into a doctrine event listener, you can easily add the container.
services:
my.listener:
class: Acme\SomeBundle\Listener\YourListener
arguments: [@container_or_entity_manager]
tags:
- { name: doctrine.event_listener, event: postLoad }
Upvotes: 0