Где хранить расчеты по данным в Symfony?
Например, у меня есть объекты:
City:
- name (string)
- men (int)
- women (int)
- streets (Collection)
public function getMenAndWomenIn33rd()
{
$count = 0;
foreach ($this->getDistricts() as $district) {
if ($district == '33rd') $count++;
}
return $this->getMen() + $this->getWomen() + $count;
}
Streets:
- city_id (relation)
- name
- district
И, например, я хотел бы посчитать среднее количество мужчин и женщин на улице в округе 33-го и передать это в шаблон.
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$city = $em->getRepository('AppBundle:City')->findOneByName('New York');
return $this->render('city/index.html.twig', array('name' => $city))
}
Шаблон:
{% block body %}
City: {{ city.name }}
//others data...
33rd: {{ city.getMenAndWomenIn33rd() }}
{% endblock %}
Метод getMenAndWomenIn33rd () должен быть в City entity
? Может в репозитории? В репозитории должны быть операции с базой данных? Может быть, в обслуживании? Я знаю, что это не может быть на контроллере, потому что контроллер должен только передавать данные.
Я знаю — я могу сделать это в репозитории с помощью GROUP BY, но я предпочитаю иметь только один запрос (findOneBy — затем я изменяю его на построитель запросов с объединениями).
Я бы сказал, что сущности должны быть очень прямыми. Никаких расчетов делать не следует, так как эту роль субъекта сохраняет государство.
Вы можете создать конкретный сервис, в котором будут выполняться все расчеты, или вы можете создать TwigExtension, если они нужны вам только для отображения некоторых данных и не используются в других местах вашего приложения. Конечно, вы можете создать сервис, а затем внедрить его в TwigExtension. Зависит от ваших потребностей.
Хороший подход — хранить всю бизнес-логику на сервисном уровне.
Я предпочитаю следующую структуру приложения Symfony:
В вашем случае может существовать служба CalculationsService, которая может запросить хранилище для всех мужчин или женщин в округе, рассчитать все необходимые данные и передать int обратно контроллеру как простой int или DTO.