Api platform教程13--错误处理

Mario Sanchez

36 people read
Thumbnail

我们在使用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来判断,如果是生产坏境才处理。

About Me

我是一位精通 Symfony 框架和 API Platform 的开发者,擅长构建高效、可扩展的 Web 应用程序和 API。 此外,我还具备 PrestaShop 模块开发经验,能够为您的电商平台定制功能,满足特定业务需求。