วิธีรับอินสแตนซ์ของเอนทิตีอ้างอิง


35

field_imageฉันมีวัตถุโหนดกับข้อมูลภาพชื่อ เมื่อฉันทำ

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

ฉันได้รับอาร์เรย์ที่มีคุณสมบัติบางอย่างแทนเอนทิตีวัตถุ อาร์เรย์มีลักษณะดังนี้:

'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

ฉันจำเป็นต้องโหลดเอนทิตีของไฟล์โดยใช้target_idหรือด้วยวิธีการรับวัตถุเอนทิตีที่อ้างอิงจากอินสแตนซ์ของโดยอัตโนมัติDrupal\image\Plugin\Field\FieldType\ImageItemหรือไม่

ทำไมกิจการที่อ้างอิงถึงไม่สามารถเข้าถึงได้ผ่านทาง getter มันอาจจะขี้เกียจโหลดถ้ามันไม่สามารถใช้ได้ทันที


$ node-> get ('imagefield') -> first () -> getTarget () ถ้ามีเพียงหนึ่งรายการหรือ $ node-> get ('imagefield') -> referencedEntities () ... จริง ๆ แล้วอันสุดท้ายคือ ทั้งหมดที่คุณต้องการ.

@IvanJaros PHP Fatal error: Call to undefined method Drupal\image\Plugin\Field\FieldType\ImageItem::getTarget()ไม่ว่า: อย่างไรก็ตามการ $node->get('imagefield')->referencedEntities()ทำงานต้องขอบคุณความจริงที่$node->get('imagefield')ส่งคืนอินสแตนซ์EntityReferenceFieldItemListซึ่งใช้referencedEntities()วิธี ดังนั้นวิธีการแก้ปัญหาของคุณเป็นเพียงบางส่วน - มันใช้งานได้กับรายการ แต่ไม่ใช่สำหรับฟิลด์เดียว
SiliconMind

ใช่ถูกต้อง getTarget อยู่ในประเภทข้อมูลอ้างอิงเอนทิตีไม่ใช่รายการฟิลด์

คำตอบ:


63

เส้นทางไปยังเอนทิตีที่อ้างอิงนั้นยาวมาก:

// $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.

แน่นอนหนึ่งยังสามารถรับได้ผ่านสายซับหนึ่ง แต่ก็ยังเป็นเรื่องยุ่งยากและฉันสงสัยว่าทำไมEntityReferenceItemไม่ให้วิธีการที่จะกลับวัตถุเอนทิตีอ้างอิง

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

นอกจากนี้ยังเป็นที่น่าสังเกตว่ามันค่อนข้างง่ายที่จะได้รับอาร์เรย์ของเอนทิตีที่อ้างอิงทั้งหมด:

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

มันทำงานได้เพราะสำหรับเขตข้อมูลอ้างอิงเอนทิตี$node->get($field)ส่งคืนอินสแตนซ์EntityReferenceFieldItemListซึ่งใช้referencedEntities()วิธีการ


33

คุณสามารถใช้ได้:

$node->field_image->entity

ถ้าคุณต้องการค่าแรก


9
นี่คือสาเหตุที่วิธีการเวทมนต์ไม่ดี ไม่มีวิธีที่จะบันทึกเอกสารนี้ในรหัสและไม่มีวิธีการคิดออกโดยดูที่อินเทอร์เฟซที่ใช้งาน
SiliconMind

6
มันยากที่จะจัดทำเอกสารในรหัสบางที แต่มีเป็นเอกสาร: wizzlern.nl/sites/wizzlern.nl/files/artikel/... เนื่องจากโครงสร้างแบบไดนามิกวิธีการไม่ได้ผลดีกว่าคุณไม่สามารถคิดได้ว่าคุณกำลังทำงานกับชั้นเรียนแบบใดเพราะทุกอย่างถูกสร้างขึ้นร่วมกันแบบไดนามิก อาจเป็นเรื่องยากที่จะหาเป็นครั้งแรก แต่ก็ง่ายที่จะจำได้เมื่อคุณทำ
Berdir

1
มีdrupal.org/project/agcobcauซึ่งจะช่วยให้มีการดำเนินการเสร็จสมบูรณ์อัตโนมัติใน IDEs
larowlan

11
@Berdir ฉันเข้าใจว่าอย่างไรก็ตามนี่ยังคงเป็นการออกแบบที่ไม่ดี ดูที่นี่: $node->get('field_image')->entityส่งคืนFileเอนทิตี อย่างไรก็ตาม$node->get('field_image')->getEntity()ส่งคืนNodeเอนทิตีหลัก! ฉันเข้าใจว่าวิธีเวทมนต์อาจใช้งานได้ แต่เป็น PITA ในโครงการขนาดใหญ่ ทำไมต้องเขียนอินเตอร์เฟซและรหัส oo หากเราสนับสนุนให้ใช้เวทย์มนตร์? คุณเขียนมันง่ายพอที่จะจำได้เมื่อคุณทำ - ฉันไม่เห็นด้วย เมื่อคุณเริ่มทำสิ่งนี้คุณจะพัฒนานิสัยที่แย่มาก ๆ ซึ่งจะทำให้โค้ดของคุณอ่านง่ายขึ้นและบำรุงรักษาได้น้อยลง
SiliconMind

4
downvoted ฉันเคยทำแบบนี้ อย่างไรก็ตามสิ่งนี้จะแตกถ้าบางครั้งการอ้างอิงเอนทิตีไม่ได้ถูกโหลดมาก่อน (ผลลัพธ์จะเป็นอาร์เรย์ที่มี target_id แทนที่จะเป็นเอนทิตีที่สร้างอินสแตนซ์) วิธีการที่สรุปโดย SiliconMind จะจัดการทุกกรณีอย่างถูกต้องและจะส่งคืนคลาสเอนทิตีที่สร้างอินสแตนซ์หากฟิลด์ไม่ว่างเปล่า
Alexander Varwijk

8

สิ่งที่ทำงานให้ฉันคือ:

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

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

คำตอบอื่น ๆ ไม่ได้สร้างอาร์เรย์ฟิลด์เอนทิตีที่ฉันคาดไว้


8

สำหรับวิธีรับเอนทิตีจากฟิลด์อ้างอิง ฉันเห็นด้วยกับ @SiliconMind เกี่ยวกับ referencedEntities ซึ่งส่งคืนอาร์เรย์ของเอนทิตีวัตถุที่คีย์โดยเดลตารายการฟิลด์

ง่าย ๆ :

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

EntityReferenceFieldItemList :: referencedEntities

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.