首页 > 解决方案 > 我可以通过 API 平台获取违规条目的 IRI 吗?

问题描述

我有一个 Symfony 5 项目,它使用symfony/api(API 平台)和一个带有UniqueEntity约束的实体(见下文。为了更好的易读性,我省略了字段注释,因为它们在这里不相关。):

/**
 * @ORM\Entity(repositoryClass=CartItemRepository::class)
 * @ApiResource(
 *     collectionOperations={"get","post"},
 *     itemOperations={"get","patch"},
 *     normalizationContext={"groups"={"cart_item:read"}}
 * )
 * @UniqueEntity(fields={"product","cart"})
 */
class CartItem
{
    private $id;
    private $product;
    private $quantity;
    private $cart;

    /* ... */
}

假设我有一些数据:

----------------------------------------
| id | product_id | cart_id | quantity |
|  1 |          3 |       2 |        1 |
|  2 |          2 |       2 |        2 |
----------------------------------------

现在如果我发送这个 POST 请求:

{
  "product": "/api/products/3",
  "quantity": 1,
  "cart": "/api/carts/2"
}

我当然会期待这个响应,因为400插入这个条目会破坏ID 1 已经使用的唯一性:[product_id,cart_id][3,2]

{
  "@context": "/api/contexts/ConstraintViolationList",
  "@type": "ConstraintViolationList",
  "hydra:title": "An error occurred",
  "hydra:description": "product: This value is already used.",
  "violations": [
    {
      "propertyPath": "product",
      "message": "This value is already used."
    }
  ]
}

我的问题是:我是否有办法获取“重复”的实体的 IRI 或 ID?(这里,ID 应该是 1,IRI 应该是/api/cart_items/1)。我想要实现的是ON DUPLICATE KEY UPDATE quantity = quantity + :quantity通过检测此错误并在发生时发送请求来重现 MySQL 的行为,PATCH但是要发送PATCH请求,我需要 IRI,或者至少需要我想要修补的项目的 ID。

编辑 :

我在 Profiler 中看到这是可见的(请参见cause下面的字段),但我无法获得 API 的响应......

Symfony\Component\Validator\ConstraintViolation {#2332 ▼
  -message: "This value is already used."
  -messageTemplate: "This value is already used."
  -parameters: [▶]
  -plural: null
  -root: App\Entity\CartItem {#675 ▼
    -id: null
    -product: App\Entity\Product {#1888 …}
    -quantity: 1
    -cart: App\Entity\Cart {#2119 …}
  }
  -propertyPath: "product"
  -invalidValue: App\Entity\Product {#1888 …}
  -constraint: Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity {#2130 …}
  -code: "23bd9dbf-6b9b-41cd-a99e-4844bcf3077f"
  -cause: [▼
    App\Entity\CartItem {#2330 ▼
      -id: 2
      -product: App\Entity\Product {#1888 …}
      -quantity: 2
      -cart: App\Entity\Cart {#2119 …}
    }
  ]
}

标签: phpsymfonyapi-platform.com

解决方案


在这种情况下,我总是使用 API 过滤器(https://api-platform.com/docs/core/filters/)。在发送 POST 请求之前,发送 GET 请求以检查实体是否存在。例如,为过滤器添加注释:

use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;

/**
 * @ORM\Entity(repositoryClass=CartItemRepository::class)
 * @ApiResource(
 *     collectionOperations={"get","post"},
 *     itemOperations={"get","patch"},
 *     normalizationContext={"groups"={"cart_item:read"}}
 * )
 * @UniqueEntity(fields={"product","cart"})
 *
 * @ApiFilter(SearchFilter::class, properties={"product": "exact", "cart": "exact"})
 */
class CartItem
{
    private $id;
    private $product;
    private $quantity;
    private $cart;

    /* ... */
}

并使用 URL 获取现有实体,如下所示:GET /cart_items?product=3&cart=2你应该得到一个集合。因此,如果 "hydra:totalItems" > 0从响应中,您可以从"hydra:member"[0]


推荐阅读