Рейтинг:1

Внедрение НОВОГО экземпляра службы в другой класс службы

флаг de

У меня есть служба (для отправки предупреждений об ошибках), которая используется несколькими другими службами.

Служба предупреждений внедряется в эти классы через соответствующие файлы services.yml и их конструкторы.

Однако оба класса совместно используют один и тот же экземпляр службы (чего я до сих пор не осознавал). Если я устанавливаю свойство из одного класса, оно доступно для использования другим классом позже.

В некоторых случаях это будет здорово, но в моем случае использования я хочу, чтобы каждый класс начинался с нового экземпляра класса службы оповещения.

Есть ли способ добиться этого с помощью services.yml, конструкторов или любых других средств?

Jaypan avatar
флаг de
Сервисы по дизайну являются синглтонами - они должны создаваться только один раз. Службы предоставляют функциональные возможности, они не обязательно предназначены для хранения данных, поэтому, вероятно, вам нужно переосмыслить архитектуру хранения данных и хранить их относительно объекта или в классе, вызывающем службу.
Geat avatar
флаг de
Это имеет смысл. Существует ли несинглтонный эквивалент сервиса, который можно внедрить в класс?
Jaypan avatar
флаг de
Нет, но если бы это был не синглтон, его не нужно было бы вводить, вы можете просто создать новый экземпляр своего класса по мере необходимости.
Geat avatar
флаг de
Я предпочитаю идею использования фабричного сервиса, особенно для классов, которые имеют множество аргументов конструктора.
4uk4 avatar
флаг cn
В Drupal службы по умолчанию являются синглтонами (общими). Но вы можете определить необщую службу. См. https://symfony.com/doc/current/service_container/shared.html.
Geat avatar
флаг de
@ 4k4 У меня сложилось впечатление, что Drupal не предназначен для использования сервисов, но это именно то, что я искал.
Рейтинг:3
флаг cn

The direct answer is quoting the Symfony documentation:

In the service container, all services are shared by default. This means that each time you retrieve the service, you’ll get the same instance. This is usually the behavior you want, but in some cases, you might want to always get a new instance.

In order to always get a new instance, set the shared setting to false in your service definition:

# config/services.yaml
services:
    App\SomeNonSharedService:
        shared: false
        # ...

https://symfony.com/doc/current/service_container/shared.html

Discussing Drupal intentions is difficult because there aren't many references. When Drupal 8 was designed this service setting didn't exist and the predecessor was back then already disputed because of the now removed request scope. I couldn't find any references that Drupal is biased against using non-shared services. In the contrary, here a discussion where core finally switched from a factory to a non-shared service, which in fact is also a factory based solution, only that this is a factory already implemented in Symfony:

https://www.drupal.org/project/drupal/issues/2660124#comment-12318542

Рейтинг:2
флаг ph

Есть пара вариантов, которые приходят на ум:

  1. Создайте фабричную службу, которая предоставляет экземпляры вашего неслужебного класса предупреждений.
  2. Реализуйте свой класс предупреждений в виде плагина

Какой из них вы выберете, действительно зависит от вашей архитектуры.

Geat avatar
флаг de
Я провел рефакторинг кода, и фабричный сервис прекрасно работает.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.