Api-平台:对 DELETE 操作使用 validation_groups
Api-Platform: use validation_groups on DELETE action
我试图阻止删除具有某些特定内容的实体。
所以我添加了一个验证规则,它与使用表单验证的常规控制器完美配合。
//entity
/**
* @Assert\IsTrue(message="Delete not allowed", groups="delete")
*
* @return bool
*/
public function isDeleteAllowed(): bool
{
//some logic here...
return false;
}
现在我想为 api-平台部分重用相同的逻辑。
我已经为我的实体的删除操作设置了一个验证组
//entity
/**
* @ApiResource(
* itemOperations={
* "delete"={
* "validation_groups"={"delete"}
* }
* })
*/
但是 api-platform DELETE 操作正在跳过验证。
我该如何执行?
供您参考,我发现它在 api 平台源代码中不起作用的原因是他们故意忽略对 DELETE 操作的验证。于是开了工单看看能不能修好Validation on DELETE action
这是我们通过在事件订阅者中反转它来解决 ApiPlatform 中的这种硬编码行为的解决方案:
<?php
//src\EventSubscriber\DeleteValidationSubscriber.php
namespace App\EventSubscriber;
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use ApiPlatform\Core\Util\RequestAttributesExtractor;
use ApiPlatform\Core\Validator\ValidatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class DeleteValidationSubscriber implements EventSubscriberInterface
{
private $validator;
private $resourceMetadataFactory;
/**
* @param ValidatorInterface $validator
* @param ResourceMetadataFactoryInterface $resourceMetadataFactory
*/
public function __construct(ValidatorInterface $validator, ResourceMetadataFactoryInterface $resourceMetadataFactory)
{
$this->validator = $validator;
$this->resourceMetadataFactory = $resourceMetadataFactory;
}
/**
* Validates data returned by the controller for DELETE action because api-platform is ignoring it
*
* @param ViewEvent $event
* @throws ResourceClassNotFoundException
*/
public function onKernelView(ViewEvent $event)
{
$controllerResult = $event->getControllerResult();
$request = $event->getRequest();
if (
$controllerResult instanceof Response
|| !$request->isMethod('DELETE')
|| $request->isMethodSafe()
|| !($attributes = RequestAttributesExtractor::extractAttributes($request))
|| !$attributes['receive']
) {
return;
}
$resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']);
$validationGroups = $resourceMetadata->getOperationAttribute($attributes, 'validation_groups', null, true);
if (!is_null($validationGroups)) {
$this->validator->validate($controllerResult, ['groups' => $validationGroups]);
}
}
/**
* @return array|string[]
*/
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => ['onKernelView', 64],
];
}
}
有了它,只要在“删除”项目操作上明确定义“validation_groups”而无需其他额外代码,验证就会按预期工作。
我试图阻止删除具有某些特定内容的实体。 所以我添加了一个验证规则,它与使用表单验证的常规控制器完美配合。
//entity
/**
* @Assert\IsTrue(message="Delete not allowed", groups="delete")
*
* @return bool
*/
public function isDeleteAllowed(): bool
{
//some logic here...
return false;
}
现在我想为 api-平台部分重用相同的逻辑。 我已经为我的实体的删除操作设置了一个验证组
//entity
/**
* @ApiResource(
* itemOperations={
* "delete"={
* "validation_groups"={"delete"}
* }
* })
*/
但是 api-platform DELETE 操作正在跳过验证。 我该如何执行?
供您参考,我发现它在 api 平台源代码中不起作用的原因是他们故意忽略对 DELETE 操作的验证。于是开了工单看看能不能修好Validation on DELETE action
这是我们通过在事件订阅者中反转它来解决 ApiPlatform 中的这种硬编码行为的解决方案:
<?php
//src\EventSubscriber\DeleteValidationSubscriber.php
namespace App\EventSubscriber;
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use ApiPlatform\Core\Util\RequestAttributesExtractor;
use ApiPlatform\Core\Validator\ValidatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class DeleteValidationSubscriber implements EventSubscriberInterface
{
private $validator;
private $resourceMetadataFactory;
/**
* @param ValidatorInterface $validator
* @param ResourceMetadataFactoryInterface $resourceMetadataFactory
*/
public function __construct(ValidatorInterface $validator, ResourceMetadataFactoryInterface $resourceMetadataFactory)
{
$this->validator = $validator;
$this->resourceMetadataFactory = $resourceMetadataFactory;
}
/**
* Validates data returned by the controller for DELETE action because api-platform is ignoring it
*
* @param ViewEvent $event
* @throws ResourceClassNotFoundException
*/
public function onKernelView(ViewEvent $event)
{
$controllerResult = $event->getControllerResult();
$request = $event->getRequest();
if (
$controllerResult instanceof Response
|| !$request->isMethod('DELETE')
|| $request->isMethodSafe()
|| !($attributes = RequestAttributesExtractor::extractAttributes($request))
|| !$attributes['receive']
) {
return;
}
$resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']);
$validationGroups = $resourceMetadata->getOperationAttribute($attributes, 'validation_groups', null, true);
if (!is_null($validationGroups)) {
$this->validator->validate($controllerResult, ['groups' => $validationGroups]);
}
}
/**
* @return array|string[]
*/
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => ['onKernelView', 64],
];
}
}
有了它,只要在“删除”项目操作上明确定义“validation_groups”而无需其他额外代码,验证就会按预期工作。