ここで私の問題です。
ボートのリストがあります。各ボートには、取り付けることができるエンジンのリストがあります。特定のエンジンはどのような種類のボートにも取り付けることができるため、エンジンはボートに結合されていません。
ボートはコンテンツタイプ、エンジンはコンテンツタイプです。ボートには複数のエンジンのフィールドがあります。
これをjsonでこのように出力したい:
[{
"title":"boat_name",
"engines":[{
"title":"engine_name",
"model":"model_nr"
},{
"title":"engine_name2",
"model":"model_nr2"
}]
}]
RESTエクスポートビューを作成することにより、RESTful Webサービスモジュールを通じてこれを達成しようとしましたが、json出力を提供するように見えるフォーマッターがありません。あなたが達成できることを理解しました View Field View を使用してこれを実行しますが、私の場合、特定のボートへの参照をエンジンに持たせる必要がありますね。
これを達成する他の方法はありますか?
カスタムノーマライザを作成して使用すると、ビューはそれを尊重します。その中で、好きなように出力構造を作成できます。
以下はクラスの例です。「コレクション」はコンテンツタイプです。
<?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エクスポートディスプレイから出力を取得するよりもはるかに簡単です。出力は自由に作成できます。
したがって、あなたのケースでは、「コレクション」を「ボート」に置き換え、コンテンツタイプが「ボート」であることを確認し、必要に応じて応答を作成します。