为了账号安全,请及时绑定邮箱和手机立即绑定

我可以通过API平台获取违规条目的IRI吗?

我可以通过API平台获取违规条目的IRI吗?

PHP
呼啦一阵风 2023-08-06 14:36:35
我有一个 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"}我当然会期待这个响应,因为插入此条目会破坏because is 已被 ID 1 使用的400唯一性:[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通过检测此错误并PATCH在发生错误时发送请求来重现 MySQL 的行为,但要发送请求PATCH,我需要 IRI,或者至少需要我想要修补的项目的 ID。
查看完整描述

2 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

在这种情况下,我总是使用 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从响应中,您可以从中检索 iri"hydra:member"[0]


查看完整回答
反对 回复 2023-08-06
?
慕标5832272

TA贡献1966条经验 获得超4个赞

您需要创建自定义 @Assert,因为这是您使用处理该作业的两个服务的唯一方法:

  1. 购物车项目存储库,

  2. 虹膜转换器接口

首先,创建 Constraint 类MyUniqueCartItem。向类声明其用法,以便您可以在验证期间访问所有属性:

public function getTargets()

{

    return self::CLASS_CONSTRAINT;

}

然后,创建MyUniqueCartItemValidator,并将之前的两个服务自动连接到它。使用CartItemRepository检查实体是否已存在,并使用IriConverterInterface检索 IRI:


public function validate($value, Constraint $constraint)

{

    // i make it short, just take look ath  the doc

    $criteria = ['cart' => $value->getCart(), 'product' => $value->getProduct()]

    $duplicated = $this->cartItemRepository->findOneBy($criteria);

    if ($duplicated !== null) {

        $iri = $this->iriConverterInterface->getIriFromItem($duplicated);

        $this->context->buildViolation("Duplicated entity : $iri" )

                ->atPath('whatever')

                ->addViolation();

    }

}


请注意,您可以通过向MyUniqueCartItem添加一些属性(在其中指定所需条件和存储库)来将MyUniqueCartItem设为通用约束MyUniqueEntity。在MyUniqueEntityValidator中,将CartItemRepository替换为EntityManagerInterface并获取存储库:


$repository = $this->entityManger->getRepository($constraint->entityClass);


查看完整回答
反对 回复 2023-08-06
  • 2 回答
  • 0 关注
  • 79 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信