Как передать контекстные подсказки субресурсам при использовании собственного провайдера данных сущностей? - PullRequest
0 голосов
/ 04 июля 2019

У меня есть объект Address.Этот адрес имеет страну.К этой стране прикреплено многоязычное поле.

GET /address/{id} возвращает стремительное расширение страны как часть ее продукции.Я бы хотел, чтобы потребитель REST API мог передавать Accept-Locale: fr_FR (или аналогичный) и получать правильный перевод для страны.

У меня есть существующая настройка перевода на основе Gedmo / Transurable пакет.Он отлично работает для отдельных лиц.Я передаю информацию о локали:1012 *

Пользовательский сериализатор, который назначает языковой стандарт контексту с помощью шаблона декоратора:
// Extracted from overall class "TranslatableContextBuilder"
    /**
     * {@inheritDoc}
     *
     * Adds the 'locale' to $context, which will be the 2-character
     * preferred language string ('en', 'fr', 'es', 'pt') that the user
     * wishes for the requested content.
     */
    public function createFromRequest(
      Request $request,
      bool $normalization,
      ?array $extractedAttributes = null
    ): array {
        $context = $this->decorated->createFromRequest(
          $request,
          $normalization,
          $extractedAttributes
        );
        // Add locale info to every context.
        $context['locale'] = $this->localeListener->getPreferredLanguage(
          $request
        );

        return $context;
    }
Поставщик данных элемента, который расширяет \ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider.Это используется для установки локали для результата, полученного из ItemDataProvider, чтобы он возвращал результат, соответствующий языку:

    /**
     * {@inheritdoc}
     *
     * Assigns the locale to the result obtained from
     * ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider.
     *
     * @see \App\EventListener\LocaleListener::onKernelRequest
     * @see \App\Serializer\TranslatableContextBuilder::createFromRequest
     *   Involved in the translation process.
     *
     */
    public function getItem(
      string $resourceClass,
      $id,
      string $operationName = null,
      array $context = []
    ) {
        $result = parent::getItem(
          $resourceClass,
          $id,
          $operationName,
          $context
        );
        if (!is_subclass_of($resourceClass, TranslatableInterface::class)) {
            return $result;
        }
        if ( ! isset($context['locale'])) {
            throw new LogicException(
              'This request requires a locale, but none was passed.  You should pass the locale as an "Accept-Language" header.  See https://www.w3.org/TR/ltli/ for the format of the value.'
            );
        }

        // Normalize the locale.
        // @TODO: duplicative with \App\EventListener\LocaleListener::onKernelRequest; DRY this out.
        $accept_language = Locale::getPrimaryLanguage($context['locale']);
        /* @var TranslatableInterface $result */

        if (null !== $result) {
            $result->setAcceptLanguage($accept_language);
        }

        return $result;
    }

В приведенном выше примере Country будет реализовывать TranslatableInterfaceпотому что у него есть переводимое поле.Address не будет.

Проблема, с которой я сталкиваюсь, заключается в том, что я думал, что \ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider::getItem вызывается рекурсивно, например, сначала getItem будет вызываться для Address, а затем getItem будет вызыватьсядля Country, чтобы я мог изменить результаты конкретного объекта.Похоже, что это не так.

Я ищу любые предложения, которые люди могут дать о том, что делать здесь.Должен ли я пытаться подключиться к другому событию или услуге?Должен ли я стремиться к расширению доктрины 1037 *?

Буду признателен за любые предложения.Заранее спасибо.

...