微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

API 平台:具有嵌套实体的组仅在删除 @ApiResource 时才起作用

如何解决API 平台:具有嵌套实体的组仅在删除 @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",writableLink=false)
     */
    private $issue;

进程类

/**
 * 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",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"
      }

解决方法

事实证明,解决方案就在我们眼皮底下,@ApiProperty(readableLink=false,writableLink=false) 注释是罪魁祸首。 The documentation regarding this annotation 明确指出,这会强制将引用的实体序列化为 IRI(否决序列化组)。从 Goals::$processus 属性中删除此注释将使 API 平台使用 goals-write 序列化组来序列化引用的 Processus 实体。

这是一个用 PHP 8 和 API Platform 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;
}

流程

<?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;
}
,

问题是你在类目标中使用了错误的构造:

* @ORM\JoinColumns({
*   @ORM\JoinColumn(name="processus_id",referencedColumnName="id")
* })

注解@JoinColumns只能用于@ManyToMany关系,在@JoinTable注解内部。

你可以看看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 在他的评论中向您建议的那样。

希望能帮到你。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。