#php #symfony
#php #symfony
Вопрос:
Как передать динамическую переменную из контроллера в службу? Я хочу управлять некоторыми параметрами в конструкторе моего сервиса, которые зависят от значения json. Мой сервис принимает два параметра в конструкции: сервис и переменную с JSON.
Для первого я передал его непосредственно в service.yaml. Для второго у меня есть некоторые трудности.
В контроллере я получаю из API JSON. Но в этом json это может быть null.
class IndexController extends AbstractController
{
/**
* @Route("/converter-hl7", name="converter", methods={"POST"})
*/
public function index(Request $request, $myjson = null) {
$myjson = $request->getContent();
global $kernel;
$converter = $kernel->getContainer()->get('app.converter');
$xml = $converter->outputXML();
$response = new Response($xml);
$response->headers->set('Content-Type', 'xml');
return $response;
}
Я сохраняю JSON в своем файле .env, MYJSON=null.
Это мой service.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
AppController:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
# explicitly configure the service
app.error:
class: AppServiceError
public: true
autowire: true
app.converter:
class: AppServiceConverterHl7Refacto
public: true
autowire: true
arguments:
$error: '@app.error'
$json: '%env(MYJSON)'
Итак, в моем сервисе вызывается ConverterHl7Refacto.php , у меня есть два параметра в конструкторе. Я хотел бы управлять параметрами, если json пуст или отсутствует. Если я выполняю dd() из $json, я получаю ‘%env (MYJSON)’ вместо JSON. Почему?
class ConverterHl7Refacto
{
private $ricetta;
private $identificativiDocumento;
private $codiceDocumento;
private $infoDocumento;
private $assistiti;
private $partecipanti;
private $relatedDoc;
private $structuredBody;
private $root;
private $error;
public function __construct(string $json,Error $error) {
$this->error = $error;
if ($json){
$this->ricetta = new Ricetta(json_decode($json));
$this->root = new Root();
$this->identificativiDocumento = new Identificativi();
$this->codiceDocumento = new CodiceDocumento($this->ricetta);
$this->infoDocumento = new InfoDocumento($this->ricetta);
$this->assistiti = new Assistiti($this->ricetta);
$this->partecipanti = new Partecipanti($this->ricetta);
$this->relatedDoc = new RelatedDocument($this->ricetta);
$this->structuredBody = new StructuredBody($this->ricetta);
}
}
Комментарии:
1. ‘%env(MYJSON)’ подразумевает, что у вас есть переменная среды с именем MYJSON, поэтому для нее не будет установлено значение $myjson . По сути, контейнер не поддерживает то, что вы пытаетесь сделать. Добавьте метод init в свой конвертер и вызовите его с помощью $myjson . Или, возможно, лучшее решение, создайте себе фабрику конвертеров. Не по теме, но вы также должны вводить свой конвертер, а не извлекать его непосредственно из контейнера.
2. Можете ли вы привести мне пример этой фабрики конвертеров? И, в функции init, что он должен вернуть? Спасибо!
Ответ №1:
Ничего особенно сложного в концепции factory. Фабрика в основном используется для создания экземпляра заданного типа. Я не тестировал следующий код, поэтому приношу извинения за опечатки:
class Error {}
class Converter {
public function __construct(string $json, Error $error)
{
// Whatever
...
class ConverterFactory {
private $error;
public function __construct(Error $error) {
$this->error = $error;
}
public function create(string $json) : Converter {
return new Converter($json,$this->error);
}
}
class MyController {
public function action(ConverterFactory $converterFactory)
{
$json = $request->getContent();
$converter = $converterFactory->create($json);
Вам нужно будет исключить ваш класс Converter из autowire в ваших сервисах.файл yaml. Но это должно быть все, что вам нужно. Нет необходимости явно определять такие вещи, как app.converter, поскольку autowire позаботится обо всем этом.
Комментарии:
1. он выдает мне эту ошибку: контроллер «App Controller IndexController::index()» требует, чтобы вы указали значение для аргумента «$ json». Либо аргумент имеет значение null, и значение null не было предоставлено, значение по умолчанию не было предоставлено, либо после этого аргумента есть необязательный аргумент.
2. Я изменил код контроллера. Вам действительно стоит взглянуть на документы и привести несколько примеров, чтобы увидеть, как все работает.