在RESTAPI中重新索引ArrayCollection元素

时间:2016-02-07 06:46:07

标签: json rest symfony arraycollection

想象一下,我有一个数组集合$items,并在我的removeItem实体类中实现了一个方法SomeEntity

public function removeItem(Item $item)
{
    $this->items->removeElement($item);
    return $this;
}

和接收PATCH请求的控制器操作:

public function patchAction(Request $request, SomeEntity $entity) {
    $form = ...;

    $form->handleRequest($request);
    if ($form->isValid()) {
        ...
        $this->get('doctrine.orm.entity_manager')->flush();

        return $entity;
    }

    return $form;
}

想象一下,SomeEntity类的实例将项目保存为[0 => {ITEM}, 1 => {ITEM}, 2 => {ITEM}, 3 => {ITEM}](索引的对象数组)。如果您向getAction发送请求并以JSON格式接收前项目中的SomeEntity对象,则对象中这些项的类型将是一个索引的对象数组(您可以使用它们迭代它们)数组方法),但是如果使用PATCH方法从对象中删除其中一个或多个并接收JSON响应,则会得到一个包含对象的Object类型,因为在PATCH请求和SomeEntity对象之后删除了一些键响应中的类不再包含索引数组,而是会有一个对象对象。这是因为,当你将数组转换为json对象时,你可以得到两个不同的结果

  1. 如果键被索引(例如:0,1,2,3,...)
  2. ,则为对象数组(数组)
  3. 对象(数组)的对象(如果未对键进行索引(例如:0,2,3,6,...)
  4. 此时我通过修改(手动重新创建元素)实体类中现有的removeItem方法解决了这个问题,如下所示:

    public function removeItem(Item $item)
    {
        $this->items->removeElement($item);
    
        if (!$this->items->isEmpty()) {
            $items = new ArrayCollection();
            foreach ($this->items as $item) {
                $items->add($item);
            }
    
            $this->items = $items;
        }
    
        return $this;
    }
    

    可能有更好的解决方法吗?你是如何解决这个问题的?

    我正在使用FOSRestBundle和JmsSerializerBundle。

1 个答案:

答案 0 :(得分:3)

这似乎是一个常见问题 - 有关此问题的其他人,请参阅https://github.com/schmittjoh/JMSSerializerBundle/issues/373。在您删除项目的函数中,除了循环遍历每个元素之外,肯定有一种更短的方法来解决它:

public function removeItem(Item $item)
{
    $this->items->removeElement($item);
    $this->items= new ArrayCollection($this->items->getValues());

    return $this;
}

该故障单中列出的其他解决方法可能适合您的需求,也可能不适合您的需求 - 如果您需要全局解决方案,您可以override the JsonSerializationVisitor类转换为数组。