API平台-如何更新和嵌入关系并保留其ID

时间:2020-06-01 18:00:11

标签: php symfony api-platform.com

我有两个实体

QuoteQuoteProduct之间具有OneToMany关系。

当我执行PUT请求以更新嵌入式QuoteProduct关系时,它将始终删除所有项并将其添加,直到结果生成新ID。

根据官方文档https://api-platform.com/docs/core/serialization/#denormalization 我应该可以通过传递他的ID来更新特定项目

报价实体

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Ramsey\Uuid\Uuid;
use ApiPlatform\Core\Annotation\ApiResource;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Serializer\Annotation\Groups;


/**
 * @ApiResource(
 *     normalizationContext={"groups"={"quote.read"}},
 *     denormalizationContext={"groups"={"quote.write"}},
 *     collectionOperations={
 *         "get"={"access_control"="is_granted('ROLE_USER')", "access_control_message"="You do not have the permission to get"},
 *         "post"={"access_control"="is_granted('ROLE_COMMERCIAL')", "access_control_message"="You do not have the permission to add"}
 *     },
 *     itemOperations={
 *         "get",
 *         "put"={"access_control"="is_granted('ROLE_COMMERCIAL')", "access_control_message"="You do not have the permission to update"},
 *         "delete"={"access_control"="is_granted('ROLE_COMMERCIAL')", "access_control_message"="You do not have the permission to delete."}
 *     },
 *     attributes={"force_eager"=false}
 * )
 * @ORM\Entity
 * @ORM\Table(name="`quotes`")
 */
class Quote
{


    public function __construct()
    {
        $this->id = Uuid::uuid4();
        $this->products = new ArrayCollection();
    }


    /**
     *
     * @ORM\Id
     * @ORM\Column(type="uuid", unique=true)
     */
    private $id;



    /**
     * @var Collection|QuoteProduct[]
     *
     * @Groups({"quote.read", "quote.write"})
     * @ORM\OneToMany(targetEntity="App\Entity\QuoteProduct", mappedBy="quote", cascade={"persist"}, orphanRemoval=true)
     * @ORM\OrderBy({"code" = "ASC"})
     */
    private $products;




    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ----------------------------------------GETTER AND SETTER------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */


    public function getId()
    {
        return $this->id;
    }


    /**
     * @return Collection|QuoteProduct[]
     */
    public function getProducts(): Collection
    {
        return $this->products;
    }

    /**
     * @param QuoteProduct $product
     * @return Quote
     */
    public function addProduct(QuoteProduct $product): self
    {
        if(false === $this->products->contains($product))
        {
            $product->setQuote($this);
            $this->products->add($product);
        }
        return $this;
    }

    /**
     * @param QuoteProduct $product
     * @return Quote
     */
    public function removeProduct(QuoteProduct $product)
    {
        if(!$this->products->contains($product))
        {
            return;
        }
        $this->products->removeElement($product);
        $product->setQuote(null);
    }



}

?>

报价产品实体

<?php


namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Ramsey\Uuid\Uuid;
use ApiPlatform\Core\Annotation\ApiResource;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Serializer\Annotation\Groups;


/**
 * @ApiResource(
 *     normalizationContext={"groups"={"quote-product.read"},"enable_max_depth"=true},
 *     denormalizationContext={"groups"={"quote-product.write"},"enable_max_depth"=true},
 *     attributes={"force_eager"=false}
 * )
 * @ORM\Entity
 * @ORM\Table(name="`quote_products`")
 */
class QuoteProduct
{

    /**
     *
     * @ORM\Id
     * @ORM\Column(type="uuid", unique=true)
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Groups({"quote-product.read", "quote-product.write", "quote.read", "quote.write"})
     *
     */
    private $code;


    /**
     * @ORM\ManyToOne(targetEntity="Quote", cascade={"persist"}, inversedBy="products")
     * @Assert\Valid
     * @Groups({"quote-product.read", "quote-product.write", "quote.read", "quote.write"})
     */
    private $quote;




    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ----------------------------------------GETTER AND SETTER------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */
    /* ---------------------------------------------------------------------------------------------- */


    public function __construct()
    {
        $this->id = Uuid::uuid4();
    }

    public function getId()
    {
        return $this->id;
    }






    public function getQuote(): ?Quote
    {
        return $this->quote;
    }

    public function setQuote(?Quote $quote)
    {
        $this->quote = $quote;

        return $this;
    }




    public function getCode(): ?string
    {
        return $this->code;
    }

    public function setCode(?string $code): self
    {
        $this->code = $code;

        return $this;
    }


}

获取报价请求/ fbe01952-2a23-4882-bb9f-970e8598f979

结果:

{
  "@context": "\/contexts\/Quote",
  "@id": "\/quotes\/fbe01952-2a23-4882-bb9f-970e8598f979",
  "@type": "Quote",
  "products": [
    {
      "@id": "\/quote_products\/15216edd-dd5c-49d5-bf3f-39d389d804d6",
      "@type": "QuoteProduct",
      "code": "Code 1",
      "quote": "\/quotes\/fbe01952-2a23-4882-bb9f-970e8598f979"
    }
  ]
}

提出报价请求/ fbe01952-2a23-4882-bb9f-970e8598f979 JSON参数(请注意,我更改了QuoteProduct代码属性的值)

{
  "@context": "\/contexts\/Quote",
  "@id": "\/quotes\/fbe01952-2a23-4882-bb9f-970e8598f979",
  "@type": "Quote",
  "products": [
    {
      "@id": "\/quote_products\/15216edd-dd5c-49d5-bf3f-39d389d804d6",
      "@type": "QuoteProduct",
      "code": "A new code",
      "quote": "\/quotes\/fbe01952-2a23-4882-bb9f-970e8598f979"
    }
  ]
}

结果为:

{
  "@context": "\/contexts\/Quote",
  "@id": "\/quotes\/fbe01952-2a23-4882-bb9f-970e8598f979",
  "@type": "Quote",
  "products": [
    {
      "@id": "\/quote_products\/865da321-dd74-4a39-82a3-e0e935555262",
      "@type": "QuoteProduct",
      "code": "A new code",
      "quote": "\/quotes\/fbe01952-2a23-4882-bb9f-970e8598f979"
    }
  ]
}

代码已更改,但已生成一个新的@id。

1 个答案:

答案 0 :(得分:-2)

几个小时后,我设法找到答案,我用参数发布了我的请求:

Content-Type : application/json;charset=UTF-8

当我使用Content-Type : application/ld+json时,它会按预期工作

根据API平台文档https://api-platform.com/docs/core/content-negotiation/,这是有道理的:不鼓励使用原始JSON或原始XML格式,请改用JSON-LD,因为它提供了更多功能并且易于使用