Метод отношений платформы API GET - PullRequest
0 голосов
/ 11 марта 2019

Я создаю API с платформой API для отображения всех моих проектов в формате JSON.
У меня уже есть свои сущности и отношения, все работает отлично.
Но проблема в том, что, когда я пытаюсь получить все проекты, где установлена ​​связь, он отображает URL-адрес API с идентификатором, а не отображает имя.

Вот возвращаемый JSON:

{
  "@context": "/api/contexts/Projets",
  "@id": "/api/projets",
  "@type": "hydra:Collection",
  "hydra:member": [
    {
      "@id": "/api/projets/78",
      "@type": "Projets",
      "id": 78,
      "titre": "Pwet",
      "date": "2021-01-01T00:00:00+01:00",
      "description": "jtyrtjhetrjrtj",
      "image": "rtjrtjrt",
      "lienGit": "rtjrtjrtjrtj",
      "lienProjet": "rtjtrjtrjtrjrtj",
      "technologies": [
        "/api/technologies/10", <- I would like the technologie name
        "/api/technologies/17",
        "/api/technologies/18",
        "/api/technologies/19",
        "/api/technologies/20",
        "/api/technologies/21",
        "/api/technologies/22",
        "/api/technologies/23",
        "/api/technologies/24",
        "/api/technologies/25",
        "/api/technologies/26",
        "/api/technologies/36",
        "/api/technologies/37"
      ],
      "outils": [
        "/api/outils/4", <- I would like the outil name
        "/api/outils/5"
      ]
    }
  ]
}

1 Ответ

2 голосов
/ 12 марта 2019

Это стандартное поведение API Platform. Он не может знать, чего именно вы хотите, если вы не укажете это в коде. К сожалению, вы не предоставили код для своих сущностей, поэтому я немного импровизирую в следующем примере.

Прежде всего вы должны понять некоторые принципы проектирования REST API. Предоставление что-то вроде /api/technologies/37 позволит потребителям выполнить еще один HTTP-запрос GET для извлечения ресурса Technologie (или Technology ). То же самое относится к Outil (или Tool ).
Если вы предоставите только название технологии, как потребители получат другие свойства этого ресурса?

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

Projet.php

namespace App\Entity; // just an example, your namespace might differ

use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(
 *     attributes={
 *         "normalization_context"={"groups"={"read"}},
 *     }
 * )
 */
class Projet
{
    /**
     * @Groups({"read"})
     */
    private $id;

    /**
     * @Groups({"read"})
     */
    private $titre;

    // other fields ...
    /**
     * @Groups({"read"})
     */
    private $technologies;

    // more fields, getters, setters, ...
}

Technologie.php

namespace App\Entity; // just an example, your namespace might differ

use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(
 *     attributes={
 *         "normalization_context"={"groups"={"read"}},
 *     }
 * )
 */
class Technologie
{
    private $id;

    /**
     * @Groups({"read"})
     */
    private $name;

    private $someOtherProperty;

    // otehr fields, getters, setters, ...
}

Теперь это будет извлекать значение для имени свойства, например:

// ... beginning
"technologies": [
    {
        "@id": "technologies/10",
        "@type": "Technologie",
        "name": "Une technologie superbe"
    },
    // ... other technologies
],
// ... ending

Этот подход очень хорошо объяснен в документации .

И здесь вы в конце концов подумаете над вопросом перед примером кода. Что покупатель собирается с именем? Это все, что им нужно знать о технологии? Будут ли они выдавать дополнительный запрос GET для получения ресурса Technologie ?

Если и только если name является уникальным свойством Technologie , вы можете изменить идентификатор с id на name :

namespace App\Entity; // just an example, your namespace might differ

use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;

/**
 * @ApiResource()
 */
class Technologie
{
    /**
     * @ApiProperty(identifier=false)
     */
    private $id;

    /**
     * @ApiProperty(identifier=true)
     */
    private $name;

    // otehr fields, getters, setters, ...
}

В этом случае выходные данные будут выглядеть (при условии, что значение для имени равно superbe ):

// ... beginning
"technologies": [
    "/api/technologies/superbe",
    // ... other technologies
],
// ... ending

Потребителю придется отправить запрос GET на /api/technologies/superbe, чтобы получить ресурс Technologie с указанным именем. Это просто идентификатор, а не идентификатор, а имя.

При разработке REST API вы должны заранее продумать, как он будет использоваться.
Если я выдаю запрос GET для /api/projets/78, нужно ли мне получать все связанные technologies и outils? Это сэкономит потребителю на выдаче ряда дорогостоящих HTTP-запросов, но результат будет довольно громоздким, и ему может не понадобиться все это.
Или мне будет предоставлена ​​возможность выдавать дальнейшие запросы GET на те ресурсы, которые мне нужны. Тогда я получу более легкий ответ, но придется делать дополнительные HTTP-запросы.

Вы можете прочитать статью в Википедии о HATEOAS , которая частично связана с вашей проблемой.

...