symfony 更新API Platform 3.0中的相关实体

tp5buhyn  于 2023-01-13  发布在  其他
关注(0)|答案(1)|浏览(138)

我尝试通过主实体更新相关实体。例如,我有产品和优惠。我执行POST/products

{
    "name": "sample product",
    "offers": [
        {
            "description": "sample offer"
        }
    ]
}

我得到的回应是

{
    "@context": "/contexts/Product",
    "@id": "/products/1",
    "@type": "Product",
    "name": "sample product",
    "offers": [
        {
            "@id": "/offers/1",
            "@type": "https://schema.org/Offer",
            "description": "sample offer"
        }
    ]
}

到目前为止一切顺利。现在,我想在/products/1上执行PUT操作

{
    "name": "product updated",
    "offers": [
        {
            "@id": "/offers/1",
            "description": "offer updated"
        }
    ]
}

并得到这个错误
执行查询时出现异常:数据库状态[23000]:完整性约束冲突:1048列'产品ID'不能为空
如果我从Offer.php中删除#[ORM\JoinColumn(nullable:false)],它可以工作,但是product_id被设置为null(行的其余部分保留),并且插入了一个新行。
我想要的是得到行更新(只是更新描述字段)。这是可能的吗?
我使用www.example.com上给出的例子,做了一些小的修改(见评论)https://api-platform.com/docs/core/getting-started/#mapping-the-entities with some minor modifications (see comments)
我的代码是:

    • 产品. php**
<?php
// api/src/Entity/Product.php
namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Serializer\Annotation\Groups; //ADDED THIS
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Entity]
#[ApiResource(
    normalizationContext: ["groups" => ["products"]],
    denormalizationContext: ["groups" => ["products"]],
)]
class Product // The class name will be used to name exposed resources
{
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
    private ?int $id = null;

    /**
     * A name property - this description will be available in the API documentation too.
     *
     */
    #[ORM\Column]
    #[Assert\NotBlank]
    #[Groups(["products"])] //ADDED THIS
    public string $name = '';

    // Notice the "cascade" option below, this is mandatory if you want Doctrine to automatically persist the related entity
    /**
     * @var Offer[]|ArrayCollection
     *
     */
    #[ORM\OneToMany(targetEntity: Offer::class, mappedBy: 'product', cascade: ['persist'])]
    #[Groups(["products"])] //ADDED THIS
    public iterable $offers;

    public function __construct()
    {
        $this->offers = new ArrayCollection(); // Initialize $offers as a Doctrine collection
    }

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

    // Adding both an adder and a remover as well as updating the reverse relation is mandatory
    // if you want Doctrine to automatically update and persist (thanks to the "cascade" option) the related entity
    public function addOffer(Offer $offer): void
    {
        $offer->product = $this;
        $this->offers->add($offer);
    }

    public function removeOffer(Offer $offer): void
    {
        $offer->product = null;
        $this->offers->removeElement($offer);
    }

    // ...

    //ADDED THIS SET AND GET
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    public function getName()
    {
        return $this->name;
    }
}
    • 提供. php**
<?php
// api/src/Entity/Offer.php
namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups; //ADDED THIS
use Symfony\Component\Validator\Constraints as Assert;

/**
 * An offer from my shop - this description will be automatically extracted from the PHPDoc to document the API.
 *
 */
#[ORM\Entity]
#[ApiResource(types: ['https://schema.org/Offer'])]
class Offer
{
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
    private ?int $id = null;

    #[ORM\Column(type: 'text')]
    #[Groups(["products"])] //ADDED THIS
    public string $description = '';

    #[ORM\Column]
    #[Assert\Range(minMessage: 'The price must be superior to 0.', min: 0)]
    public float $price = 1.0; //MODIFIED THIS

    #[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'offers')]
    #[ORM\JoinColumn(nullable:false)] //ADDED THIS
    public ?Product $product = null;

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

    //ADDED THIS SET AND GET
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    public function getDescription()
    {
        return $this->description;
    }
}
dgtucam1

dgtucam11#

尝试使用PATCH方法而不是PUT,并将Content-Type头设置为application/merge-patch+json
PUT方法需要填充每个已知属性,否则它将认为该属性已被删除,因此将其设置为null。这就是为什么您的id设置为null
PATCH方法只编辑json中属性。
不要忘记执行以下操作:https://api-platform.com/docs/core/content-negotiation/#configuring-patch-formats
您可以阅读:为了得到适当的解释,这是我们都犯的错误,哈哈

相关问题