使用相关/嵌入式实体

时间:2015-07-19 14:53:10

标签: php orm doctrine-orm zend-framework2 apigility

原始Github问题:https://github.com/zfcampus/zf-apigility-doctrine/issues/215

在代码连接的API中,三个实体及其各自的服务:场地,产品和位置。

Venue与Location

有ManyToOne关系
   /**
     * @ORM\ManyToOne(targetEntity="Db\Entity\Location", cascade={"persist"})
     * @ORM\JoinColumn(name="location_id", referencedColumnName="id")
     *
     * @var Db\Entity\Location $location
     */
    protected $location;
    public function getLocation() {...}
    public function setLocation($location) {...}

Venue与Product

有很多关系
/**
 * @ORM\ManyToMany(targetEntity="Db\Entity\Product", inversedBy="venues", cascade={"persist"})
 * @ORM\JoinTable(name="products_venues")
 **/
protected $products;
public function getProducts() {...}
public function setProducts($products) {...}
public function addProduct(Product $product)
{
    $product->addVenue($this);
    $this->products[] = $product;

    return $this;
}

产品与Venue有很多关系

/**
 * @ORM\ManyToMany(targetEntity="Db\Entity\Venue", mappedBy="products", cascade={"persist"})
 **/
protected $venues;
public function getVenues() {...}
public function setVenues($venues) {...}
public function addVenues($venue)
{
    $this->venues[] = $venue;

    return $this;
}

现在,我有两个问题: 1)我可以创建一个新的场地和位置信息,如下所示:

POST /venues
{
  .
  .
  .
  "location":{
      "address":"123 Fake Street",
      "city":"cityTest",
      "country":"CountryTest",
      "postalCode":"12345"
  }
}

使用新的位置注册表创建一个新的Venue,当我获取刚刚创建的场地时,看到两个正确链接。 当我得到刚刚创建的Venue Id时,我在_embedded中找到了其id的位置对象,但是如果我需要编辑该地址并将Venue 1与位置2而不是最初创建的位置1链接起来呢? / p>

其次,我无法使用产品创建和链接产品与在最后一个创建的同一POST调用中的场所重现此过程。 虚空想出了如何将现有产品添加到特定场馆的产品系列中。 那么,哪种方式更合适? (“1次调用创建并将它们全部链接”vs“多次创建调用+ Patch调用将它们链接在一起”)并且我需要在Apigility + Doctrine中使它们发生什么?

7月20日更新:

呜!!这是一个有趣的发现。为了更新特定场地的位置,我必须在Venues服务中添加一个新的“位置”字段。 有了这个,我可以将一个位置对象作为额外属性与/ Venues所需的属性一起发布。或者通过添加location: {"id" : 123}来指定id(这也适用于PATCH,这是我一直在寻找的。太棒了!)。但我意识到没有实际的验证可以检查具有指定Id的位置是否确实存在。如果没有找到,则新场地将链接到“空”位置。 :皱着眉头:

所以,在那之后,我看到了包含的Apigility Doctrine验证器。 :smile:ZF\Apigility\Doctrine\Server\Validator\ObjectExists验证我发送的对象实际存在于DB中。 Yeeyyy!我所要做的就是将其添加为“位置”字段的验证器,并根据https://github.com/doctrine/DoctrineModule/blob/master/docs/validator.md指定两个选项 entity_class = Db\Entity\Location因此验证者知道我正在尝试验证的实体,以及fields = id,这就像验证标准。

现在,当我尝试发布会场时,我需要使用"location": {"id":123}指定位置。这也适用于PATCH。当找不到具有指定Id的位置时,我收到一条很棒的错误消息,这很好。如果没有ID,则提供500个(一个问题,我猜...)。

现在,我一直在努力寻找如何将对象添加到实体集合中。 (比如,将产品添加到特定场所)。我试图将“产品”字段添加到场地服务中,但没有奏效。我一直没有收集任何产品的场地。 这就是我尝试PATCH的方式:

PATCH /venues/1
{
...
"products":[
  {"id": 5}
]
...
}

有关于此的任何想法吗?

1 个答案:

答案 0 :(得分:0)

在RESTful API中进行原子CRUD操作通常是一个好主意。

在您的情况下,这意味着最好通过名为POST|GET|DELETE|PUT /location的单独API资源来CRUD您的Location实体。

然后,API客户端首先必须检索或创建一个位置,然后才发布场地。

示例:

第1步。 创建或检索位置。

POST /location
  {
    "address":"123 Fake Street",
    "city":"cityTest",
    "country":"CountryTest",
    "postalCode":"12345"
  }

GET /location/{somefilter}

第2步。 创建场地

POST /venues
  {
    ...
    "location": 2 //the location id
    ...
  }