带有翻译器消息的 Api 平台自定义异常

Posted

技术标签:

【中文标题】带有翻译器消息的 Api 平台自定义异常【英文标题】:Api platform Custom Exception with translator message 【发布时间】:2021-03-17 06:37:27 【问题描述】:

我在 api 平台中为用户实例使用自定义端点和自定义控制器。

class PayingMembershipForOthersController


    private ValidatorInterface $validator;

    public function __construct(ValidatorInterface $validator)
    
        $this->validator = $validator;
    

    public function __invoke(User $data)
    
        $this->validator->validate($data);
        try 
           $paymentService->paymentMembership($data);
         catch(\Exception $e) 
           throw $e
        
        return $data;
    


如果找不到用户,我的 $userService 会抛出自定义异常,如下所示。

class XXXException extends \Exception

    public function __construct(
        $message = "user.notfound.message",  // Translation file key.
        $code = 0,
        Throwable $previous = null
    ) 
        parent::__construct($message, $code, $previous);
    

所以我想在这里发送翻译消息(UserNotFound [de_DE] 和 UserNotFound [en_EN]。所以你能帮我吗。

提前谢谢..!!!

【问题讨论】:

这些异常在抛出时是否被捕获或转换为Response 你能指导我如何实现“异常被缓存或在抛出时转换为响应”吗? 异常似乎被 标准化。也许您可以用一个子类的实例替换这个服务,该子类的一个实例覆盖 ::getErrorMessage 由一个执行翻译的实现?这样日志上的错误将不会被翻译,这可能解释性较差,但更容易搜索日志。 【参考方案1】:

API-Platform 有两个有用的工具来处理Exception

    exception to HTTP status, exception event subscriber。

第一个允许您从代码的任何位置抛出异常。 API-Platform 会捕获它,然后将其转换为漂亮的Response

# config/packages/api_platform.yaml

api_platform:
    # ...
    exception_to_status:
        App\Exception\MyException: 400
        App\Exception\AnotherException: 500

下一个允许捕获抛出的异常并处理它。在您的情况下,有效负载是将异常消息翻译成适当的语言。在这个例子中,我使用Symfony translator service:


namespace App\EventSubscriber;


use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Contracts\Translation\TranslatorInterface;

class ExceptionSubscriber implements EventSubscriberInterface

    private TranslatorInterface $translator;

    public function __construct(TranslatorInterface $translator)
    
        $this->translator = $translator;
    

    public static function getSubscribedEvents()
    
        return [
           KernelEvents::EXCEPTION => ['translateException'],
        ];
    

    public function translateException(ExceptionEvent $event): void
    
        $currentException = $event->getThrowable();
        $currentMessage = $currentException->getMessage();

        $translatedMessage = $this->translator->trans($currentMessage);
        $exceptionClass = get_class($currentException);
        $translatedException = new $exceptionClass($translatedMessage);

        $event->setThrowable($translatedException);
    

这样,每个未捕获的异常都会被翻译,然后转换为 HTTP 错误响应。

【讨论】:

这仅适用于我们的自定义异常吗? 当然。我猜“自定义异常”是指在您的 src 目录中声明的那些?在这种情况下,异常的全名(即命名空间 + 类名)为 App\...\MyException 。由于get_class()函数返回全名,你可以检查全名是否以“App\”开头。否则,您还可以让所有自定义异常实现自定义接口(例如TranslatableExceptionInterface)并使用if ($exception instanceof TranslatableExceptionInterface) //translate

以上是关于带有翻译器消息的 Api 平台自定义异常的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JAX-RS 异常上的自定义消息设置 40X 错误?

自定义异常消息:最佳实践

如何为 graphql 创建自定义错误/异常处理程序?

自定义异常中的损坏消息

UICollectionView 使用自定义布局抛出未捕获的异常

自定义异常中的默认消息 - Python