4

I have an entity, such as Game, with some properties like time, and it has a load of Event entities underneath it. Some information about the game is implicitly stored in the entities, e.g. the number of deaths (given by the number of death events).

If I want to display the number of deaths in a template (which has access to the game object), where do I put the logic?

I can think of a few options, but I'm not sure which is the 'correct' thing to do.

  • Put a getDeaths() function in a Repository
    I get the impression that's where it's supposed to go, but I don't know how to access that properly from the template.
  • Put a getDeaths() function in the Game entity
    The easiest thing to do, because it's easily accessed from a template.
  • Create a function in the Controller
    It doesn't seem flexible to ask a controller for this information
Druckles
  • 3,161
  • 2
  • 41
  • 65

2 Answers2

1

If you're implicitly storing the number of deaths in the Game entity, then simply add a getDeaths() function to the entity. You should probably have it there anyway rather than just keeping a public variable that can be modified anyway.

The Repository method would be needed if you had to query the number of deaths from the database directly, in which case you could just pass that to the template directly.

Keep in mind you can pass any number of variables to your template, so it doesn't have to just be

return array('game' => $game);

and then in your template:

{{ game.numDeaths }}

You can just as easily pass the number of deaths to your template directly so it's easily accessible:

return array('game' => $game, 'numDeaths' => $numDeaths);

and then in your template:

{{ numDeaths }}

Hope that helps.

Jason Roman
  • 8,146
  • 10
  • 35
  • 40
  • To clarify, by saying it's stored 'implicitly', I mean that you need to use the `Event` entities stored within the game to work out the number of deaths (i.e. access the database again), rather than storing a number of deaths variable. And other answers indicate that passing the repository to the template is bad practice: http://stackoverflow.com/questions/11754077/how-can-i-access-repository-functions-in-twig-template-in-symfony2. – Druckles Dec 26 '14 at 20:54
  • Also, if there are multiple statistics I want to present, would that not create large coupling between the template and the controller? – Druckles Dec 26 '14 at 20:58
  • @Druckles the [Symfony2 documentation](http://symfony.com/doc/current/book/templating.html#embedding-controllers) shows how to pass a repository to the template, so I don't think it's a bad practice. – A.L Dec 26 '14 at 22:55
  • 1
    @A.L I couldn't find repositories mentioned in the example you linked. Which example are you talking about? – Druckles Dec 26 '14 at 23:02
  • @Jason Roman If the `Game` entity contained a list of entities (which can then be used to work out the attribute (e.g. deaths), does that count as a 'query'? I.e. could one simply put a helper function for that in the Entity declaration, or should one use the Repository? – Druckles Dec 26 '14 at 23:44
  • If it contains the list of entities then it will only count as a query if that list has to query the database and you didn't explicitly fetch with a join already. Otherwise, it won't re-query the database. Regardless, I would only pass data to you template after it has already been calculated, since the template should just be for displaying data and not making calculations. – Jason Roman Dec 27 '14 at 03:11
  • @Jason Roman In Symfony2's classic Category/Product example, where a category contains a list of products, would you, for instance, add a function getBoxes() in the `Category` entity that finds all the products that it contains that are boxes? – Druckles Dec 27 '14 at 10:31
  • Definitely not, I'd make a repository function for that – Jason Roman Dec 27 '14 at 11:01
  • @Jason Roman So a repository function e.g. `findBoxesForCategory($categoryid)`? And would you pass the repository function to the template, or create a twig extension as above? – Druckles Dec 27 '14 at 11:34
  • I wouldn't create a custom Twig extension. I might pass the *results* of the repository function to the template. Basically by the time I get to the template I don't want to be doing any additional calculations. – Jason Roman Dec 27 '14 at 16:40
  • @JasonRoman But if you have several statistics to calculate and display, would that not create high coupling between the controller and template? – Druckles Dec 28 '14 at 18:42
  • If you have several statistics to calculate, I would create a service for that. Your controller then calls those services to get the data, and then you pass the data directly to the template. That would then follow best practices of a light controller, reusable functions in a service, and Twig being used to do nothing more than display the data you've already calculated in code – Jason Roman Dec 28 '14 at 18:44
1

Use twig custom extension/functions:

public function getFunctions()
{
    return [
        new \Twig_SimpleFunction('number_of_death', [$this, 'getNumberOfDeath'])
    ]
}

public function getNumberOfDeath(Entity $entity)
{
    // logic

    return $return;
}

usage:

{{ number_of_death(entity) }}
xurshid29
  • 4,172
  • 1
  • 20
  • 25
  • I got the impression that this sort of logic shouldn't be included in templates: http://stackoverflow.com/questions/11754077/how-can-i-access-repository-functions-in-twig-template-in-symfony2. – Druckles Dec 26 '14 at 20:51
  • While creating a custom twig function is feasible, it seems unnecessary for your particular example – Jason Roman Dec 27 '14 at 04:43
  • @Druckles Where should it be included then? Twig Extension is not a template/view. It is the best place where you should put your business logic which belongs to view. – xurshid29 Dec 27 '14 at 06:50
  • @Druckles Also, I don't like to render a controller action in my views, it creates a tight coupling beetwen them.. – xurshid29 Dec 27 '14 at 06:53