Bagaimana cara mendapatkan instance dari entitas yang direferensikan?

35

Saya memiliki objek simpul dengan bidang gambar bernama field_image. Kapan saya melakukannya

$node
  ->get('field_image')
  ->first()
  ->getValue()

Saya mendapatkan array dengan beberapa properti, bukan objek entitas. Array terlihat seperti ini:

'target_id' => string '8' (length=1)
'alt' => string '' (length=0)
'title' => string '' (length=0)
'width' => string '587' (length=3)
'height' => string '458' (length=3)
'_loaded' => boolean true
  '_accessCacheability' => 
    object(Drupal\Core\Cache\CacheableMetadata)[1092]
      protected 'cacheContexts' => 
        array (size=0)
          ...
      protected 'cacheTags' => 
        array (size=0)
          ...
      protected 'cacheMaxAge' => int -1

Apakah saya harus manullay memuat entitas file menggunakan target_idatau ada cara untuk secara otomatis mendapatkan objek entitas yang direferensikan dari Drupal\image\Plugin\Field\FieldType\ImageItem?

Mengapa entitas yang direferensikan tidak dapat diakses melalui pengambil? Bisa dimuat malas jika tidak segera tersedia.

SiliconMind
sumber
$ node-> get ('imagefield') -> first () -> getTarget () jika hanya ada satu item atau $ node-> get ('imagefield') -> referencedEntities () ... sebenarnya yang terakhir adalah semua yang Anda butuhkan.
@IvanJaros Tidak persis: PHP Fatal error: Call to undefined method Drupal\image\Plugin\Field\FieldType\ImageItem::getTarget(). Namun $node->get('imagefield')->referencedEntities()berfungsi berkat fakta $node->get('imagefield')mengembalikan contoh EntityReferenceFieldItemListyang mengimplementasikan referencedEntities()metode. Jadi solusi Anda hanya sebagian - ini berfungsi untuk daftar tetapi tidak untuk bidang tunggal.
SiliconMind
Ya benar, target getT adalah pada tipe data referensi entitas, bukan item bidang.

Jawaban:

63

Jalur ke entitas yang dirujuk sangat panjang:

// $id = some node ID
// $field = field name for entity reference field
$node = Node::load($id);

/** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $referenceItem */
$referenceItem = $node->get($field)->first();

/** @var \Drupal\Core\Entity\Plugin\DataType\EntityReference $entityReference */
$entityReference = $referenceItem->get('entity');

/** @var \Drupal\Core\Entity\Plugin\DataType\EntityAdapter $entityAdapter */
$entityAdapter = $entityReference->getTarget();

/** @var \Drupal\Core\Entity\EntityInterface $referencedEntity */
$referencedEntity = $entityAdapter->getValue();

// At this point $referencedEntity is the referenced entity object.

Tentu saja kita masih bisa mendapatkannya melalui satu panggilan liner, tapi tetap saja, itu rumit dan saya bertanya-tanya mengapa EntityReferenceItemtidak memberikan metode yang akan mengembalikan objek entitas referensi.

$referencedEntity = $node
  ->get($field)
  ->first()
  ->get('entity')
  ->getTarget()
  ->getValue()
;

Perlu juga dicatat bahwa cukup mudah untuk mendapatkan array dari semua entitas yang direferensikan:

$node->get($field)->referencedEntities();

Ini berfungsi karena untuk bidang referensi entitas $node->get($field)mengembalikan instance EntityReferenceFieldItemListyang mengimplementasikan referencedEntities()metode.

SiliconMind
sumber
33

Anda dapat gunakan:

$node->field_image->entity

jika Anda menginginkan nilai pertama

larowlan
sumber
9
Inilah mengapa metode sihir itu buruk. Tidak ada cara untuk mendokumentasikan ini dalam kode dan tidak ada cara untuk mengetahui hal ini dengan melihat antarmuka yang diimplementasikan.
SiliconMind
6
Sulit untuk mendokumentasikan dalam kode mungkin, tapi ada adalah dokumentasi: wizzlern.nl/sites/wizzlern.nl/files/artikel/... . Karena strukturnya yang dinamis, metode tidak akan bekerja lebih baik, Anda tidak dapat menentukan kelas yang Anda gunakan dengan tepat karena semuanya dibangun bersama secara dinamis. Mungkin sulit ditemukan untuk pertama kalinya, tetapi cukup mudah untuk diingat begitu Anda melakukannya.
Berdir
1
Ada drupal.org/project/agcobcau yang akan membantu penyelesaian otomatis dalam IDE
larowlan
11
@Berdir Saya mengerti itu, namun ini masih desain yang buruk. Lihat ini: $node->get('field_image')->entitymengembalikan Fileentitas. Namun $node->get('field_image')->getEntity()mengembalikan Nodeentitas induk ! Saya mengerti bahwa metode sihir mungkin dapat digunakan, tetapi mereka adalah PITA dalam proyek yang lebih besar. Mengapa repot-repot menulis antarmuka dan kode oo jika kita didorong untuk menggunakan sihir? Anda menulisnya cukup mudah untuk diingat begitu Anda melakukannya - saya tidak setuju. Setelah Anda mulai melakukan ini, Anda akan mengembangkan kebiasaan yang sangat buruk yang akan membuat kode Anda kurang mudah dibaca dan kurang dapat dipertahankan.
SiliconMind
4
Diturunkan. Dulu saya melakukannya dengan cara ini. Namun ini kadang-kadang akan rusak jika referensi entitas belum dimuat sebelumnya (hasilnya akan menjadi array dengan target_id bukan entitas instantiated). Metode yang diuraikan oleh SiliconMind akan menangani dengan benar semua kasus dan akan selalu mengembalikan kelas entitas instantiated jika bidang tidak kosong.
Alexander Varwijk
8

Apa yang berhasil untuk saya adalah:

$entity_id = $node->get('field_contact')->first()->getValue()['target_id'];

$entity = Node::load($entity_id)->toArray();

Jawaban lain tidak menghasilkan array bidang entitas yang saya harapkan

AlxVallejo
sumber
8

Untuk cara mendapatkan entitas dari bidang yang dirujuk. Saya setuju dengan @SiliconMind tentang referencedEntities itu mengembalikan array objek entitas yang dikunci oleh delta item bidang.

Sederhana saja:

$node->get('field_name')->referencedEntities();

EntityReferenceFieldItemList :: referencedEntities

Carlos
sumber