Cách an toàn và thanh lịch để truy cập các thực thể lồng nhau thông qua các trường


7

Tôi đã thấy nhiều cách tiếp cận khác nhau để truy cập các giá trị thực thể trong lớp theo chủ đề. Mã dưới đây chỉ là một ví dụ đơn giản sử dụng các phương thức ma thuật. Nó giả định tất cả các giá trị được đặt - nếu bất kỳ phần nào trong đó trả về NULL, thì theo kinh nghiệm của tôi xảy ra lỗi.

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

Có những phương pháp như ->hasField->count()để kiểm tra mọi thứ, và tôi có sự đa dạng trong các chủ đề của mình. Tôi có thể hoàn thành công việc nhưng đôi khi nó cảm thấy xấu xí. Tôi quan tâm đến các mẫu mã mà các nhà phát triển sử dụng để khoan một cách an toàn và thanh lịch thông qua các tham chiếu thực thể.


1
Có một mô-đun contrib gọi là Reference_map. Nó không thân thiện với người dùng lắm, nhưng nó được viết rõ ràng cho vấn đề này.
Charles Bamford

Câu trả lời:


7

Đề xuất, tạo một đối tượng miền có logic.

Thông thường những thực thể này đại diện cho một cái gì đó phù hợp với lĩnh vực kinh doanh của bạn.

Ví dụ, trong trường hợp của bạn, nút có thể là một sự kiện.

Vì vậy, bạn có thể mô hình một đối tượng miền được gọi là 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;
  }
}

Sau đó, trong mã của bạn:

<?php

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

6

Mặc dù thông thường bạn kết xuất các đoạn văn bản theo cách đệ quy, bạn có thể truy xuất một cấu trúc cố định không đệ quy bằng cách tạo lại nó bằng các vòng lặp foreach:

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

Điều này tránh truy cập vào các trường trống và có thể xử lý các trường đa giá trị.


1

Để mở rộng câu trả lời tuyệt vời bằng 4k4 cho thấy một mẫu chúng tôi sử dụng rộng rãi nhưng không bao gồm sự tồn tại của trường, bạn có thể tạo một lớp đơn giản được tạo khuôn theo câu trả lời tuyệt vời của 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() : [];
   }
}

và sau đó foreach (EntityReferenceItemListHelper::create($paragraph->field_media)->referencedEntities() as $media) {

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.