- Published on
Api platform教程13--错误处理
原创文章,转载时需取得本人同意并注明来源
- Authors
-
-
- Name
- langziyang
-
我们在使用symfony时,可能会在Entity里对字段进行验证,比如说对身份证进行18位长度验证
#[Assert\Length(min: 18, max: 18, exactMessage: '身份证不正确')]
private ?string $idNumber = null;
此时假如我们post一条数据,idNumber小于或者大于18位,api platform会返回一条错误信息:
{
"@id": "\/api\/errors\/422",
"@type": "hydra:Error",
"title": "An error occurred",
"detail": "idNumber: 身份证不正确",
"status": 422,
"type": "\/errors\/422",
"trace": [],
"hydra:title": "An error occurred",
"hydra:description": "idNumber: 身份证不正确"
}
我们可以看到hydra:description字段提示了字段名和错误消息,对于开发者来说这是非常方便的,因为可以一目了然的知道是哪一个字段出错。但是在生产环境我们只需要给用户提示身份证不正确即可,不需要把字段名也显示给用户。那么我们如何处理呢?
根据api platform文档说明,验证错误有一个专属错误provider: api_platform.validator.state.error_provider
所以你可以自定义这个服务,有两种方式:一种是在services.yaml中对服务进行定义;如果你看过我以前的教程,你可能会记得有一个名为装饰服务的东西,没错,这比在services.yaml中定义更方便:
<?php
namespace App\State\Common\Provider;
use ApiPlatform\Metadata\HttpOperation;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ApiResource\Error;
use ApiPlatform\State\ProviderInterface;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
use function Symfony\Component\String\u;
#[AsDecorator('api_platform.validator.state.error_provider')]
final class ErrorProvider implements ProviderInterface
{
public function __construct(
#[AutowireDecorated]
private $inner
)
{
}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
$exception = $this->inner->provide($operation, $uriVariables, $context);
/** @var HttpOperation $operation */
$status = $operation->getStatus() ?? 500;
// You don't have to use this, you can use a Response, an array or any object (preferably a resource that API Platform can handle).
$error = Error::createFromException($exception, $status);
// care about hiding informations as this can be a security leak
if ($status >= 500) {
$error->setDetail('Something went wrong');
}
if ($_ENV['APP_ENV'] === 'prod') {
$detail = u($error->getDetail());
$error->setDetail($detail->slice($detail->indexOfLast(':') + 1)->trim());
}
return $error;
}
}
可以看到我们使用一句
#[AsDecorator('api_platform.validator.state.error_provider')]
就完成了整个服务的重写。 同时,我们在构造函数里写了
#[AutowireDecorated]
这样我们就可以在provide方法里通过
$exception = $this->inner->provide($operation, $uriVariables, $context);
取得被装饰服务里的返回数据.
再次提交,是否只显示了错误消息?当然,在这里你也可以通过APP_ENV来判断,如果是生产坏境才处理。