7

I've seen a variety of approaches to access entity values in the theming layer. The code below is just a simple example using magic methods. It assumes all values are set - if any part of that returns a NULL, then in my experience errors ensue.

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

There are methods like ->hasField and ->count() to check things, and i have a variety in my themes. I can get the job done but sometimes it feels ugly. I'm interested the coding patterns that devs use to safely and elegantly drill through entity references.

  • 1
    There is a contrib module called reference_map. It's not very user friendly, but it was written expressly for this issue. – Charles Bamford Jun 19 at 16:28
7

Suggestion, create a domain object that has the logic.

Normally these entities represent something that fits your business-domain.

E.g in your instance, the node might be an event.

So you might model a domain object called 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;
  }
}

Then in your code:

<?php

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

Although normally you render paragraphs recursively, you can retrieve a fixed structure non-recursively by recreating it with foreach loops:

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

This avoids accessing empty fields and is able to process multi-value fields.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.