ApiPlatform:如何更新而不是创建不是@ApiResource或@ApiSubresource的子实体

时间:2018-05-15 10:34:36

标签: api symfony api-platform.com

我有来自第三方软件包的ThirdPartyEntity,使用ThirdPartyEntityTrait,我链接到项目中的MyEntity

现在,因为ThirdPartyEntity未设置为ApiResource,也未设置为ApiSubresource,因为我在MyEntity上没有设置任何序列化组,来自ApiPlatform的MyEntity,它会返回我这样的内容:

{
   "@id":"/api/my_entities/17",
   "@type":"MyEntity",
   "id":17,
   "third_party_entity": {
      "id":22,
      "a_property":"some value"
   }
}

但如果我PUT a_property的{​​{1}}更改了body

{
   "@id":"/api/my_entities/17",
   "@type":"MyEntity",
   "id":17,
   "third_party_entity": {
      "id":22,
      "a_property":"some NEW value to update"
   }
}

我要创建一个新的third_party_entity并获得此响应:

{
   "@id":"/api/my_entities/17",
   "@type":"MyEntity",
   "id":17,
   "third_party_entity": {
      "id":23,
      "a_property":"some NEW value to update"
   }
}

那么,我如何更新third_party_entity而不是每次都创建它?

这里有相关的课程和特质

/**
 * @ORM\Table(name="app_my_entities")
 * @ORM\Entity()
 * @ApiResource()
 */
class MyEntity
{
    // !!!!!!!!!!!!!!!!!!
    // This is the trait I use to link MyEntity
    // with the entity from the third-party bundle
    // !!!!!!!!!!!!!!!!!!
    use ThirdPartyEntityTrait;

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    ...
}

这是ThirdPartyEntityTrait

trait ThirdPartyEntityTrait
{
    /**
     * @ORM\OneToOne(targetEntity="Namespace\To\Bundle\Entity\ThirdPartyEntity", cascade={"all"})
     * @ORM\JoinColumn(name="thirdPartyEntity", referencedColumnName="id")
     */
    private $thirdPartyEntity;

    /**
     * @param thirdPartyEntity $thirdPartyEntity
     *
     * @return ThirdPartyEntity
     */
    public function setThirdPartyEntity(thirdPartyEntity $thirdPartyEntity): ThirdPartyEntity
    {
        $this->thirdPartyEntity = $thirdPartyEntity;

        /** @var ThirdPartyEntity $this */
        return $this;
    }

    /**
     * @return thirdPartyEntity
     */
    public function getThirdPartyEntity(): ?thirdPartyEntity
    {
        return $this->thirdPartyEntity;
    }

    /**
     * @return thirdPartyEntity
     */
    public function removeThirdPartyEntity(): ?thirdPartyEntity
    {
        $thirdPartyEntity = $this->getThirdPartyEntity();

        $this->thirdPartyEntity = null;

        return $thirdPartyEntity;
    }
}

正如您所看到的,不再是保存关系和一些访问器方法的属性。

相反,这是链接的实体:

/**
 * @ORM\Entity()
 * @ORM\Table(name="third_party_entities")
 */
class ThirdPartyEntity
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @ORM\Column(name="aProperty", type="string", nullable=true)
     */
    private $aProperty;

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

    public function getAProperty()
    {
        return $this->aProperty;
    }

    public function setAProperty($aProperty)
    {
        $this->aProperty = $aProperty;

        return $this;
    }
}

This question is cross-posted also on GitHub.

1 个答案:

答案 0 :(得分:1)

解决方案非常简单:使用另一种配置方法!

实际上,可以混合使用配置类型,因此,可以将注释与yaml配置一起使用。

鉴于此,在config/api_platform/third_party_entity.yaml中创建一个新的配置文件就足够了。

在其中放入了从第三方捆绑包映射实体所需的配置:

resources:
    App\Entity\MyEntity:
        properties:
            remote:
                subresource:
                    resourceClass: 'Third\Party\Bundle\TheBundle\Entity\ThirdPartyEntity'
    Third\Party\Bundle\TheBundle\Entity\ThirdPartyEntity:

通过这种方式,可以将我们无法通过注释访问的第三方捆绑包中的实体配置为子资源。