API 平台:具有嵌套实体的组仅在删除 @ApiResource 时有效
API Platform : Groups with nested entities work only when removing @ApiResource
API 平台默认使用 IRI 获取嵌套实体,但我正在尝试获取使用 normalization_context 和组规范化的实体。它有效,但只有当我从嵌套实体中删除 @ApiResource 并且我需要它来公开我的 CRUD 服务时。
例子
/**
* @ApiResource(
* attributes={
* "normalization_context"={"groups"={"goals-read"}},
* "denormalization_context"={"groups"={"goals-read"}}
* })
*
* )
*
* Goals
* @ApiFilter(OrderFilter::class, properties={"id"}, arguments={"orderParameterName"="order"})
* @ORM\Table(name="goals", indexes={@ORM\Index(name="IDX_C7241E2FA55629DC", columns={"processus_id"})})
* @ORM\Entity
*/
class Goals
{
/**
* @var int
* @Groups("goals-read")
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
// some fields ...
/**
* @var Processus
* @ORM\ManyToOne(targetEntity="Processus")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="processus_id", referencedColumnName="id")
* })
* @Groups({"goals-read"})
* @ApiProperty(readableLink=false, writableLink=false)
*/
private $processus;
/**
* @var Issues
* @ORM\ManyToOne(targetEntity="Issues")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="issues_id", referencedColumnName="id")
* })
* @Groups({"goals-read"})
* @ApiProperty(readableLink=false, writableLink=false)
*/
private $issue;
进程Class
/**
* Processus
* @ApiResource()
* @ORM\Table(name="processus", indexes={@ORM\Index(name="IDX_EEEA8C1DC35E566A", columns={"family_id"})})
* @ORM\Entity
*/
class Processus
{
/**
* @var int
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
* @Groups({"goals-read"})
*/
private $id;
/**
* @var string|null
* @ORM\Column(name="name", type="string", length=255, nullable=true)
* @Groups({"goals-read"})
*/
private $name;
响应正文
{
"@context": "/api/contexts/Goals",
"@id": "/api/goals",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/api/goals/29",
"@type": "Goals",
"id": 29,
"description": "string",
"comment": "string",
"currentState": "string",
"goalToReach": "string",
"advancement": "string",
"indicator": 0,
"q1": "string",
"q2": "string",
"q3": "string",
"q4": "string",
"nextYear": "string",
"nextTwoYear": "string",
"processus": "/api/processuses/2",
"issue": "/api/issues/5"
}
删除@ApiResource()时
// JSON 响应
...
...
...
"processus": {
"@type": "Processus",
"@id": "_:938",
"id": 2,
"name": "string"
}
问题是你在 class 目标中使用了错误的结构:
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="processus_id", referencedColumnName="id")
* })
注解@JoinColumns只能用于@ManyToMany关系,在@JoinTable[=29里面=]注解.
你可以看看on related Doctrine documentation
因此,在您的情况下,您必须使用:
/**
* @var Processus
*
* @ORM\ManyToOne(targetEntity="Processus")
* @ORM\JoinColumn(name="processus_id", referencedColumnName="id")
*
* @Groups({"goals-read", "goals-write"})
*/
private $processus;
是的,我为非规范化上下文添加了不同的序列化组 goals-write,正如@Jeroen van der Laan 在他的评论中向您建议的那样。
希望能帮到你
原来解决方案就在我们眼皮底下,@ApiProperty(readableLink=false, writableLink=false)
注释是罪魁祸首。 The documentation regarding this annotation 明确指出这会强制将引用的实体序列化为 IRI(否决序列化组)。从 Goals::$processus
属性 中删除此注释将使 API 平台使用 goals-write
序列化组来序列化引用的 Processus
实体。
这是一个在 PHP 8 和 API 平台 2.6 中编写的工作示例(因为这是我在编写本文时目前部署的,但不要认为这里的版本是相关的):
目标
<?php declare(strict_types = 1);
//..
/**
* @ORM\Entity
*/
#[ApiResource(
normalizationContext: [
'groups' => [
'goals-read'
]
],
)]
#[ApiFilter(
OrderFilter::class,
properties: ['id'],
arguments: [
'orderParameterName' => 'order'
]
)]
class Goals
{
/**
* @ORM\Id
* @ORM\GeneratedValue(
* strategy="IDENTITY"
* )
* @ORM\Column(
* type="integer",
* nullable=false
* )
* @Groups({
* "goals-read"
* })
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(
* targetEntity="Processus"
* )
* @ORM\JoinColumn(
* name="processus_id",
* referencedColumnName="id"
* )
* @Groups({
* "goals-read"
* })
* NO MORE @ApiProperty ANNOTATION HERE
*/
private ?Processus $processus = null;
}
Processus
<?php declare(strict_types = 1);
//..
/**
* @ORM\Entity
*/
#[ApiResource]
class Processus
{
/**
* @ORM\Id
* @ORM\GeneratedValue(
* strategy="IDENTITY"
* )
* @ORM\Column(
* type="integer",
* nullable=false
* )
* @Groups({
* "goals-read"
* })
*/
private ?int $id = null;
/**
* @ORM\Column(
* name="name",
* type="string",
* length=255,
* nullable=true
* )
* @Groups({
* "goals-read"
* })
*/
private ?string $name = null;
}
API 平台默认使用 IRI 获取嵌套实体,但我正在尝试获取使用 normalization_context 和组规范化的实体。它有效,但只有当我从嵌套实体中删除 @ApiResource 并且我需要它来公开我的 CRUD 服务时。
例子
/**
* @ApiResource(
* attributes={
* "normalization_context"={"groups"={"goals-read"}},
* "denormalization_context"={"groups"={"goals-read"}}
* })
*
* )
*
* Goals
* @ApiFilter(OrderFilter::class, properties={"id"}, arguments={"orderParameterName"="order"})
* @ORM\Table(name="goals", indexes={@ORM\Index(name="IDX_C7241E2FA55629DC", columns={"processus_id"})})
* @ORM\Entity
*/
class Goals
{
/**
* @var int
* @Groups("goals-read")
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
// some fields ...
/**
* @var Processus
* @ORM\ManyToOne(targetEntity="Processus")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="processus_id", referencedColumnName="id")
* })
* @Groups({"goals-read"})
* @ApiProperty(readableLink=false, writableLink=false)
*/
private $processus;
/**
* @var Issues
* @ORM\ManyToOne(targetEntity="Issues")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="issues_id", referencedColumnName="id")
* })
* @Groups({"goals-read"})
* @ApiProperty(readableLink=false, writableLink=false)
*/
private $issue;
进程Class
/**
* Processus
* @ApiResource()
* @ORM\Table(name="processus", indexes={@ORM\Index(name="IDX_EEEA8C1DC35E566A", columns={"family_id"})})
* @ORM\Entity
*/
class Processus
{
/**
* @var int
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
* @Groups({"goals-read"})
*/
private $id;
/**
* @var string|null
* @ORM\Column(name="name", type="string", length=255, nullable=true)
* @Groups({"goals-read"})
*/
private $name;
响应正文
{
"@context": "/api/contexts/Goals",
"@id": "/api/goals",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/api/goals/29",
"@type": "Goals",
"id": 29,
"description": "string",
"comment": "string",
"currentState": "string",
"goalToReach": "string",
"advancement": "string",
"indicator": 0,
"q1": "string",
"q2": "string",
"q3": "string",
"q4": "string",
"nextYear": "string",
"nextTwoYear": "string",
"processus": "/api/processuses/2",
"issue": "/api/issues/5"
}
删除@ApiResource()时
// JSON 响应
...
...
...
"processus": {
"@type": "Processus",
"@id": "_:938",
"id": 2,
"name": "string"
}
问题是你在 class 目标中使用了错误的结构:
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="processus_id", referencedColumnName="id")
* })
注解@JoinColumns只能用于@ManyToMany关系,在@JoinTable[=29里面=]注解.
你可以看看on related Doctrine documentation
因此,在您的情况下,您必须使用:
/**
* @var Processus
*
* @ORM\ManyToOne(targetEntity="Processus")
* @ORM\JoinColumn(name="processus_id", referencedColumnName="id")
*
* @Groups({"goals-read", "goals-write"})
*/
private $processus;
是的,我为非规范化上下文添加了不同的序列化组 goals-write,正如@Jeroen van der Laan 在他的评论中向您建议的那样。
希望能帮到你
原来解决方案就在我们眼皮底下,@ApiProperty(readableLink=false, writableLink=false)
注释是罪魁祸首。 The documentation regarding this annotation 明确指出这会强制将引用的实体序列化为 IRI(否决序列化组)。从 Goals::$processus
属性 中删除此注释将使 API 平台使用 goals-write
序列化组来序列化引用的 Processus
实体。
这是一个在 PHP 8 和 API 平台 2.6 中编写的工作示例(因为这是我在编写本文时目前部署的,但不要认为这里的版本是相关的):
目标
<?php declare(strict_types = 1);
//..
/**
* @ORM\Entity
*/
#[ApiResource(
normalizationContext: [
'groups' => [
'goals-read'
]
],
)]
#[ApiFilter(
OrderFilter::class,
properties: ['id'],
arguments: [
'orderParameterName' => 'order'
]
)]
class Goals
{
/**
* @ORM\Id
* @ORM\GeneratedValue(
* strategy="IDENTITY"
* )
* @ORM\Column(
* type="integer",
* nullable=false
* )
* @Groups({
* "goals-read"
* })
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(
* targetEntity="Processus"
* )
* @ORM\JoinColumn(
* name="processus_id",
* referencedColumnName="id"
* )
* @Groups({
* "goals-read"
* })
* NO MORE @ApiProperty ANNOTATION HERE
*/
private ?Processus $processus = null;
}
Processus
<?php declare(strict_types = 1);
//..
/**
* @ORM\Entity
*/
#[ApiResource]
class Processus
{
/**
* @ORM\Id
* @ORM\GeneratedValue(
* strategy="IDENTITY"
* )
* @ORM\Column(
* type="integer",
* nullable=false
* )
* @Groups({
* "goals-read"
* })
*/
private ?int $id = null;
/**
* @ORM\Column(
* name="name",
* type="string",
* length=255,
* nullable=true
* )
* @Groups({
* "goals-read"
* })
*/
private ?string $name = null;
}