Использование Symfony @ParamConverter для передачи ассоциативного массива объектов в качестве параметра

#php #symfony

Вопрос:

Я использую symfony @ParamConverter в своем контроллере для передачи массива объектов. Я могу успешно передать массив объектов, используя следующую конфигурацию:

 * @ParamConverter("arrayOfObjects", class="array<MyServiceMyClass>", converter="fos_rest.request_body")
 

Что я получаю внутри контроллера, так это следующее:

 arrayOfObjects = [
    [0] => {MyServiceMyClass}[3],
    [1] => {MyServiceMyClass}[3],
    [2] => {MyServiceMyClass}[3]
]
...
 

Однако в создаваемом мной ПОСТ-вызове используется следующий текст:

 {
    "id_1": {
        "name": "name 1",
        "description": "desc 1",
        "number": "number 1",
    },
    "id_2": {
        "name": "name 2",
        "description": "desc 2",
        "number": "number 2",
    },
...
}
 

Теперь я в идеале хочу, чтобы @ParamConverter преобразовал тело во что-то вроде:

 arrayOfObjects = [
    ["id_1"] => {MyServiceMyClass}[3],
    ["id_2"] => {MyServiceMyClass}[3],
    ["id_3"] => {MyServiceMyClass}[3]
]
 

Не могли бы вы найти способ заставить это работать?

Мой контроллер:

     /**
     * @OAPost(
     *     path="/post-my-class",
     *     @OARequestBody(
     *          required=true,
     *          @OAJsonContent(
     *               ref="#/components/schemas/MyClass"
     *          )
     *     )
     *)
     * @ParamConverter("arrayOfObjects", class="array<MyServiceMyClass>", converter="fos_rest.request_body")
     *
     * @Route("/post-my-class", methods="POST")
     * @param MyClass[] $arrayOfObjects
     *
     * @return Response
     */
    public function postController(array $arrayOfObjects): Response
    {
       // Some logic ...
    }
 

Мой класс:

 class MyClass
{
    /**
     * @var string
     * @OAProperty(
     *     type = "string",
     *     property="name"
     * )
     * @SerializerType(name="string")
     */
    private $name;

    /**
     * @var string
     * @OAProperty(
     *     type = "string",
     *     property="description"
     * )
     * @SerializerType(name="string")
     */
    private $description;

    /**
     * @var string
     * @OAProperty(
     *     type = "string",
     *     property="number"
     * )
     * @SerializerType(name="string")
     */
    private $number;

    /**
     * MyClass constructor.
     *
     * @param string $name
     * @param string $description
     * @param string $number
     */
    public function __construct(
        string $name,
        string $description,
        string $number
    ) {
        $this->name = $name;
        $this->description = $description;
        $this->number = $number;
    }
...
}

 

Примечание: Если я использую

  * @ParamConverter("arrayOfObjects", class="array", converter="fos_rest.request_body")
 *
 * @Route("/post-my-class", methods="POST")
 * @param array $arrayOfObjects
 

Я получаю:

 arrayOfObjects = [
    ["id_1"] => {array}[3],
    ["id_2"] => {array}[3],
    ["id_3"] => {array}[3]
]
 

что близко к тому, что я хочу, но входной параметр преобразуется не в объект MyClass, а в обычный массив.

Комментарии:

1. Зачем вам нужны ключи? «id_1», «id_2» и т.д.?

2. Вот как делается запрос. Я не имею на это никакого влияния. Они мне нужны для того, чтобы различать объекты на основе их id .

Ответ №1:

Почему бы просто не получить его. Тело запроса в самом методе?

    /**
     * @Route("/test", name="test")
     */
    public function test(Request $request)
    {
        $contentJson=$request->getContent();
        $data=json_decode($contentJson,true);}
 

Комментарии:

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