我是API Platform的新手,我需要验证路由的ID参数,以验证它是否是Symfony/API Platform应用程序上的整数。
当我查询GET /api/customers/{id}
时,我想检查{id}的值,如果它无效,则抛出异常。
例如:GET /api/customers/10
它按预期工作,如果资源不存在,我会得到HTTP 200状态代码或404 Not Found。GET /api/customers/abc
或GET /api/customers/-1
返回404 Not Found错误,但在本例中,我希望返回400 Bad Request错误。我该怎么做?
我遵循documentation创建了一个EventSubscriber,如下所示:
// src/EventSubscriber/CustomerManager.php
final class CustomerManager implements EventSubscriberInterface
{
/**
* @return array[]
*/
public static function getSubscribedEvents(): array
{
return [
KernelEvents::VIEW => ['checkCustomerId', EventPriorities::PRE_VALIDATE],
];
}
/**
* Check the customer ID on GET requests
*
* @param ViewEvent $event
* @return void
* @throws MalformedIdException
*/
public function checkCustomerId(ViewEvent $event)
{
$customer = $event->getControllerResult();
if (!$customer instanceof Customer || !$event->getRequest()->isMethodSafe(false)) {
return;
}
$id = $event->getRequest()->query->get('id');
if (!ctype_digit($id)) {
throw new MalformedIdException(sprintf('"%s" is not a valid customer ID', $id));
}
}
}
我试图改变优先级,但什么都没有发生。
我已经创建并注册了我的新异常:
// src/Exception/MalformedIdException.php
namespace App\Exception;
final class MalformedIdException extends \Exception
{
}
api_platform:
# ...
exception_to_status:
# The 4 following handlers are registered by default, keep those lines to prevent unexpected side effects
Symfony\Component\Serializer\Exception\ExceptionInterface: 400 # Use a raw status code (recommended)
ApiPlatform\Core\Exception\InvalidArgumentException: !php/const Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST
ApiPlatform\Core\Exception\FilterValidationException: 400
Doctrine\ORM\OptimisticLockException: 409
# Validation exception
ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException: !php/const Symfony\Component\HttpFoundation\Response::HTTP_UNPROCESSABLE_ENTITY
# Custom mapping
App\Exception\MalformedIdException: 400
我还尝试过在Customer实体上使用Asserts,但也没有成功。
当我使用php bin/console debug:event kernel.view
时,一切看起来都很好:
------- --------------------------------------------------------------------------- ----------
Order Callable Priority
------- --------------------------------------------------------------------------- ----------
#1 App\EventSubscriber\CustomerManager::checkCustomerId() 65
#2 ApiPlatform\Core\Validator\EventListener\ValidateListener::onKernelView() 64
#3 ApiPlatform\Core\EventListener\WriteListener::onKernelView() 32
#4 ApiPlatform\Core\EventListener\SerializeListener::onKernelView() 16
#5 ApiPlatform\Core\EventListener\RespondListener::onKernelView() 8
------- --------------------------------------------------------------------------- ----------
我错过了什么?
3条答案
按热度按时间6l7fqoea1#
你应该签入你的方法:
lf3rwulv2#
由于我只需要处理一个特定的错误案例,所以我找到的解决方案是实现一个ExceptionListener。
我使用了the one provided in the Symfony documentation,然后对其进行了修改,使其通过以Json格式返回所有错误来重现API平台行为。
然后,我有条件地处理了遇到404错误以及ID参数在请求中可用时的情况,如下所示:
下面是ExceptionListener的完整代码:
现在API行为是我所期望的,如下所示:
|示例请求| HTTP代码结果|
| ------------ | ------------ |
|获取
/api/customers/20
|200-确定||GET
/api/customers/15000
| 404-未找到(数据库中不存在此记录)||GET
/api/customers/abc
|400-错误请求||GET
/api/customers/-1.8
|400-错误请求|如果有人有其他方法可以达到同样的效果,但用一种更干净的方法,请毫不犹豫地提出建议!
wkyowqbh3#
如果您查看事件系统(https://api-platform.com/docs/core/events/)的文档,它说明
PRE_VALIDATE
挂钩仅支持(POST、PUT、PATCH),而不支持GET。我也遇到过同样的问题。我仍在寻找更好的解决方案。