フィールドを介してネストされたエンティティにアクセスするための安全でエレガントな方法


7

テーマ設定レイヤーでエンティティ値にアクセスするためのさまざまなアプローチを見てきました。以下のコードは、マジックメソッドを使用した簡単な例です。すべての値が設定されていることを前提としています-そのいずれかの部分がNULLを返す場合、私の経験ではエラーが発生します。

$value = $node->field_paragraph
    ->entity->field_media
    ->entity->field_file
    ->entity->field_text->value;

->hasField->count()チェックなどの方法があり、テーマも色々あります。私は仕事を成し遂げることができますが、時々それは醜く感じます。開発者がエンティティ参照を安全かつエレガントにドリルスルーするために使用するコーディングパターンに興味があります。


1
reference_mapと呼ばれるcontribモジュールがあります。ユーザーフレンドリーではありませんが、この問題のために特別に書かれました。
Charles Bamford

回答:


7

提案、ロジックを持つドメインオブジェクトを作成します。

通常、これらのエンティティは、ビジネスドメインに適合するものを表します。

たとえば、インスタンスでは、ノードはイベントである可能性があります。

したがって、というドメインオブジェクトをモデル化できますEventWrapper

<?php

namespace Drupal\my_domain;
use Drupal\node\NodeInterface;
use Drupal\media\MediaInterface;
use Drupal\file\FileInterface;

class EventWrapper {
  protected $node;
  public static function fromNode(NodeInterface $node): EventWrapper {
    $instance = new static();
    $instance->node = $node;
    return $instance;
  }
  public function getMedia() : ?MediaInterface {
    if ($this->node->hasField('field_media') && !$this->node->get('field_media')->isEmpty()) {
      return $this->node->field_media->entity;
    }
    return NULL;
  }
  public function getMediaImage() : ?FileInterface {
    if (($media = this->getMedia()) && $media->hasField('field_file') && !$media->get('field_file')->isEmpty()) {
      return $media->field_file->entity;
    }
    return NULL;
  }
  public function getImageCaption(): ?string {
    if (($file = this->getMediaImage()) && $file->hasField('field_text') && !$file->get('field_text')->isEmpty()) {
      return $file->field_text->value;
    }
    return NULL;
  }
}

次に、コードで:

<?php

$image_caption = EventWrapper::fromNode($node)->getImageCaption();

6

通常は段落を再帰的にレンダリングしますが、固定構造をforeachループで再作成することにより、非再帰的に取得できます。

foreach ($node->field_paragraph->referencedEntities() as $paragraph) {
  foreach ($paragraph->field_media->referencedEntities() as $media) {
    ...
  }
}

これにより、空のフィールドへのアクセスが回避され、複数値フィールドを処理できます。


1

私たちが広く使用しているパターンを示し、フィールドの存在をカバーしていない4k4による素晴らしい答えを拡張するには、larowlanの素晴らしい答えを模倣した単純なクラスを作成できます。

class EntityReferenceItemListHelper {
   protected $fieldItemList;
   static function create(?EntityReferenceFieldItemListInterface $fieldItemList) {
     $instance = new static;
     $instance->fieldItemList = $fieldItemList;
   }
   public function referencedEntities(): array {
     return $this->fieldItemList ? $this->fieldItemList->referencedEntities() : [];
   }
}

その後 foreach (EntityReferenceItemListHelper::create($paragraph->field_media)->referencedEntities() as $media) {

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.