Как я могу отобразить все ошибки в формате json в friendsofsymfony / rest-bundle v3

#symfony #fosrestbundle #jmsserializerbundle #jms-serializer

#symfony #fosrestbundle #jmsserializerbundle #jms-сериализатор

Вопрос:

Я хочу перехватить все ошибки Symfony, после чего отобразить их в JSON. В friendsofsymfony / rest-bundle v2 я могу установить параметры

 fos_rest:
    exception:
        enabled: true
         exception_controller: 'AppControllerExceptionController::showAction'
    ...
  

Но в V3 параметр exception_controller удален.

Моя текущая конфигурация FOS REST:

 fos_rest:
  view:
    formats:
      xml:  false
      json: true
    view_response_listener: force
  serializer:
    groups: ['Default']
    serialize_null: true
  format_listener:
    rules:
      - { path: ^/api/v1, priorities: [ json ], fallback_format: json, prefer_extension: true }
  exception:
    enabled: true
  

В официальном руководстве говорится, что следует использовать обработчики в JMS.
https://symfony.com/doc/current/bundles/FOSRestBundle/4-exception-controller-support.html
Но он не содержит объяснения, как настроить конфигурацию в yaml.

Ответ №1:

Вы можете перехватывать все ошибки подписчика symfony

 <?php

declare(strict_types=1);

namespace AppUtilSerializerNormalizer;

use JMSSerializerContext;
use JMSSerializerGraphNavigatorInterface;
use JMSSerializerHandlerSubscribingHandlerInterface;
use JMSSerializerJsonSerializationVisitor;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentSerializerEncoderJsonEncoder;

class CustomExceptionHandler implements SubscribingHandlerInterface
{
    private bool $debug;

    public function __construct(bool $kernelDebug)
    {
        $this->debug = $kernelDebug;
    }

    public static function getSubscribingMethods(): array
    {
        return [
            [
                'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
                'format'    => JsonEncoder::FORMAT,
                'type'      => Exception::class,
                'method'    => 'serializeToJson',
                'priority'  => -1,
            ],
        ];
    }

    public function serializeToJson(
        JsonSerializationVisitor $visitor,
        Exception $exception,
        array $type,
        Context $context
    ) {
        $data = $this->convertToArray($exception, $context);

        return $visitor->visitArray($data, $type);
    }

    /**
     * @return array<string, mixed>
     */
    protected function convertToArray(Exception $exception, Context $context): array
    {
        $statusCode = null;

        if ($context->hasAttribute('template_data')) {
            $templateData = $context->getAttribute('template_data');

            if (array_key_exists('status_code', $templateData)) {
                $statusCode = $templateData['status_code'];
            }
        }

        $data['error'] = $this->getMessageFromThrowable($exception, $statusCode);

        return $data;
    }

    protected function getMessageFromThrowable(Throwable $throwable, ?int $statusCode): string
    {
        if ($this->debug) {
            return $throwable->getMessage();
        }

        return array_key_exists($statusCode, Response::$statusTexts) ? Response::$statusTexts[$statusCode] : 'error';
    }
}

  

services.yaml

  AppUtilsSerializerNormalizerCustomExceptionHandler:
     $kernelDebug: '%kernel.debug%'