Symfony использует параметры времени выполнения в сервисах - PullRequest
0 голосов
/ 02 июля 2018

Мне нужно инициализировать объект, который будет внедрен в некоторые сервисы. Некоторые из его аргументов могут быть получены во время выполнения из параметров запроса. Как мне работать с такими динамическими объектами?

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

Второй подход - пометить мой объект как "синтетический сервис". Поэтому я должен подготовить объект в конструкторе и установить его в контейнер службы.

Я не уверен, что это лучший подход. Может ли кто-нибудь подсказать мне, как действовать в таких ситуациях?

Пример псевдокода первого подхода:

class Storage {
    private $path;
    private $project;

    public function __construct($path) {
        $this->path = $path;
    }

    public function setProject($project): void {
        $this->project = $project;
    }

    public function showFullPath() {
        echo "Full path: {$this->path}/{$this->project}";
    }
}

class Service {
    private $storage;

    public function __construct(Storage $storage) {
        $this->storage = $storage;
    }

    public function doSomething($project) {
        $this->storage->setProject($project);
        $this->storage->showFullPath();
    }
}


// in controller
$service = $container->get('Service');
$service->doSomething($project);

Пример псевдокода второго подхода:

class Storage {
    private $path;
    private $project;

    public function __construct($path, $project) {
        $this->path = $path;
        $this->project = $project;
    }

    public function showFullPath() {
        echo "Full path: {$this->path}/{$this->project}";
    }
}

class Service {
    private $storage;

    public function __construct(Storage $storage) {
        $this->storage = $storage;
    }

    public function doSomething() {
        $this->storage->showFullPath();
    }
}


// in controller
$storage = new Storage($path, $project);
$container->set('Storage', $storage);

$service = $container->get('Service');
$service->doSomething();

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Я согласен с gvf, что использование подхода RequestStack является хорошим решением в этом сценарии. Однако, если вы настаиваете на использовании объекта запроса от контроллера, вы можете ввести фабричную службу для создания объекта хранения:

class StorageFactory
{
    public function createStorage(Request $request) : Storage
    {
        // ... create $storage from $request
        return $storage;
    }
}


class Service
{
    public function doSomething(Storage $storage)
    {
        // ...
    }
}

// in your controller
$storage = $container->get("storage_factory")->createStorage($request);
$container->get('Service')->doSomething($storage);

Как видите, вы должны передать объект $storage в качестве параметра методу doSomething. Невозможно установить его в конструкторе, потому что вы явно хотите создать объект $storage после настройки служб.

Между прочим: инъекция сеттера - отстой, потому что это позволяет сервисам находиться в несогласованном состоянии. Избегайте этого (и вообще сеттеров) везде, где это возможно.

0 голосов
/ 02 июля 2018

Если нужные параметры извлекаются из запроса, почему бы вам не вставить стек запроса в Storage, а затем в showFullPath просто получить нужный параметр из основного запроса стека запроса?

use Symfony\Component\HttpFoundation\RequestStack;

class Storage {
  private $path;
  private $requestStack;

  public function __construct($path, RequestStack $requestStack) {
      $this->path = $path;
      $this->requestStack = $requestStack;
  }

  public function showFullPath() {
      $project = $this->requestStack->getMasterRequest()->getYourParametersHereFromRequest();
      echo "Full path: {$this->path}/{$project";
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...