web-dev-qa-db-ja.com

RESTコンテンツのネストされたリストのエクスポート

ここで私の問題です。

ボートのリストがあります。各ボートには、取り付けることができるエンジンのリストがあります。特定のエンジンはどのような種類のボートにも取り付けることができるため、エンジンはボートに結合されていません。

ボートはコンテンツタイプ、エンジンはコンテンツタイプです。ボートには複数のエンジンのフィールドがあります。

これをjsonでこのように出力したい:

[{
    "title":"boat_name",
    "engines":[{
                 "title":"engine_name",
                 "model":"model_nr"
               },{
                 "title":"engine_name2",
                 "model":"model_nr2"
               }]
}]

RESTエクスポートビューを作成することにより、RESTful Webサービスモジュールを通じてこれを達成しようとしましたが、json出力を提供するように見えるフォーマッターがありません。あなたが達成できることを理解しました View Field View を使用してこれを実行しますが、私の場合、特定のボートへの参照をエンジンに持たせる必要がありますね。

これを達成する他の方法はありますか?

3
netla5

カスタムノーマライザを作成して使用すると、ビューはそれを尊重します。その中で、好きなように出力構造を作成できます。

以下はクラスの例です。「コレクション」はコンテンツタイプです。

<?php

declare(strict_types = 1);

namespace Drupal\mymodule\Normalizer;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Url;
use Drupal\image\Entity\ImageStyle;
use Drupal\serialization\Normalizer\ContentEntityNormalizer;
use Drupal\node\NodeInterface;

/**
 * Class CollectionNormalizer.
 *
 * @package Drupal\mymodule\Normalizer
 */
class CollectionNormalizer extends ContentEntityNormalizer {

  /**
   * The interface or class that this Normalizer supports.
   *
   * @var string
   */
  protected $supportedInterfaceOrClass = [
    'Drupal\node\NodeInterface',
  ];

  /**
   * The entity manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function supportsNormalization($data, $format = NULL) {
    if (!is_object($data) || !$this->checkFormat($format)) {
      return FALSE;
    }

    if ($data instanceof NodeInterface && $data->getType() == 'collection') {
      return TRUE;
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function normalize($entity, $format = NULL, array $context = []) {
    $attributes = [];
    $attributes['id'] = $entity->id();
    $attributes['title'] = $entity->label();
    $attributes['summary'] = $entity->get('field_summary')->value;
    $attributes['card_type'] = $entity->get('field_directory_view')->value;
    $attributes['list_image'] = NULL;
    $attributes['url'] = Url::fromRoute('entity.node.canonical', ['node' => $attributes['id']])->toString();

    $media = $entity->get('field_featured_image')->getValue();

    if (!empty($media)) {
      $item = $this->entityTypeManager->getStorage('media')->load($media[0]['target_id']);
      $image = $item->get('image')->getValue();

      $attributes['list_image'] = [
        'src' => ImageStyle::load('collection_listing')
          ->buildUrl($item->image->entity->getFileUri()),
        'alt' => $image[0]['alt'],
      ];
    }

    return $attributes;
  }

}

モジュールのservices.ymlファイルでそれを宣言する必要もあります:

  mymodule.collection_entity:
    class: Drupal\mymodule\Normalizer\CollectionNormalizer
    arguments: ['@entity_type.manager']
    tags:
      - { name: normalizer, priority: 10 }

例としてentityTypeManagerを使用して、必要な他のサービスを注入できます。

ビューは、優先度が高い限り、デフォルトの代わりにこれを使用します。 IMOは、ビューUIを使用してRESTエクスポートディスプレイから出力を取得するよりもはるかに簡単です。出力は自由に作成できます。

したがって、あなたのケースでは、「コレクション」を「ボート」に置き換え、コンテンツタイプが「ボート」であることを確認し、必要に応じて応答を作成します。

3
Kevin