API平台关联方法GET

时间:2019-03-11 18:28:16

标签: rest api symfony api-platform.com

我正在使用API​​平台创建一个API,以在JSON文件中显示我所有的开发项目。
我已经完成了我的实体和关系,完美地工作了。
但是问题是当我尝试获取所有项目时,在建立关系的地方,它显示带有ID的API URL,而不是显示名称。

这是返回的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 个答案:

答案 0 :(得分:2)

这是API平台的默认行为。除非您在代码中指定,否则它无法知道您真正想要的是什么。不幸的是,您尚未为实体提供代码,因此稍后我将在一个示例中作一些即兴的演示。

首先,您必须了解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

documentation中对此方法进行了很好的解释。

在这里,您最终将在代码示例之前想到这个问题。消费者使用的名称是什么?他们是否需要了解有关该技术的所有信息?他们会发出额外的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, ...
}

在这种情况下,输出将看起来像(假设name的值为 superbe ):

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

消费者必须向/api/technologies/superbe发出GET请求,以获取具有给定名称的资源 Technologie 。只是标识符不是ID,而是名称。

在设计REST API时,您应该提前考虑如何使用它。
如果我向/api/projets/78发出GET请求,是否需要检索所有相关的technologiesoutils?这样可以节省使用者发出大量昂贵的HTTP请求的时间,但结果将是非常庞大的,它们可能不一定需要所有这些请求。
还是可以给我所需的那些资源发出进一步的GET请求的可能性。然后,我会得到较轻的响应,但是必须发出其他HTTP请求。

您可能会阅读有关HATEOAS的Wikipedia文章,该文章与您的问题部分相关。