Вызовы метода сервиса и сеттер-внедрение

Дата обновления перевода 2023-07-06

Вызовы метода сервиса и сеттер-внедрение

Tip

Если вы используете автомонтирование, вы можете использвоать `#[Required]``, чтобы автоматически сконфигурировать вызовы метода .

Обычно, вы захотите внедрить ваши зависимости через конструктор. Но иногда, особенно, если зависимость необязательная, вы можете захотеть использовать "сеттер-внедрение". Например:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/Service/MessageGenerator.php
namespace App\Service;

use Psr\Log\LoggerInterface;

class MessageGenerator
{
    private $logger;

    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }

    // ...
}

Чтобы сконфигрурировать контейнер так, чтобы он вызывал метод setLogger, используйте ключ calls:

1
2
3
4
5
6
# config/services.yaml
services:
    App\Service\MessageGenerator:
        # ...
        calls:
            - setLogger: ['@logger']

Чтобы предоставить неизменяемые сервисы, некоторые классы реализуют неизменяемые сеттеры. Такие сеттеры возвращают новый экземпляр сконфигурированного класса вместо изменения объекта, в котором они были вызваны:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/Service/MessageGenerator.php
namespace App\Service;

use Psr\Log\LoggerInterface;

class MessageGenerator
{
    private $logger;

    public function withLogger(LoggerInterface $logger): self
    {
        $new = clone $this;
        $new->logger = $logger;

        return $new;
    }

    // ...
}

Так как метод возвращает отдельный клонированный экземпляр, конфигурация такого сервиса означает использование возватного значения метода wither ($service = $service->withLogger($logger);). Конфигурация для того, чтобы сообщить контейнеру сделать это, будет выглядеть так:

1
2
3
4
5
6
# config/services.yaml
services:
    App\Service\MessageGenerator:
        # ...
        calls:
            - withLogger: !returns_clone ['@logger']

Tip

Если включено автомонтирование, вы также можете использовать атрибуты; в предыдущем примере это будет:

1
2
3
4
5
6
7
8
9
10
11
/**
 * @return static
 */
#[Required]
public function withLogger(LoggerInterface $logger)
{
    $new = clone $this;
    $new->logger = $logger;

    return $new;
}

Вы также можете использовать преимущества возвратного типа PHP 8 static вместо аннотации @return static. Если вы не хотите метод с возвратным типом PHP 8 static и чтобы атрибут #[Required] вел себя как wither, вы можете добавить аннотацию @return $this, чтобы отключить функцию возврата клона.