Як отримати екземпляр посилання?


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/… . Завдяки динамічній структурі методи не справді працюють краще, ви не можете зрозуміти, з яким класом ви працюєте саме так, як все будується разом. Вперше це може бути важко знайти, але досить легко згадати, коли ти це робив.
Бердір

1
Є drupal.org/project/agcobcau, який допоможе автоматично заповнити IDE
larowlan

11
@Berdir Я розумію, що це, проте це все ще поганий дизайн. Подивіться на це: $node->get('field_image')->entityповертає Fileсутність. Однак $node->get('field_image')->getEntity()повертається материнська Nodeсутність! Я розумію, що магічні методи можуть бути корисними, але вони є PITA у великих проектах. Навіщо турбувати інтерфейси та код коду, якщо нас все-таки рекомендують використовувати магію? Ви написали, що досить легко запам'ятати, коли це зробили - я не згоден. Як тільки ви почнете це робити, ви виробите по-справжньому шкідливу звичку, яка зробить ваш код менш читабельним та менш реальним.
SiliconMind

4
Захищений. Раніше я робив це так. Однак іноді це порушиться, якщо посилання суб’єктів раніше не завантажувалися (результатом буде масив з target_id замість створеної сутності). Метод, викладений SiliconMind, буде належним чином обробляти всі випадки та завжди повертатиме екземплярний клас сутності, якщо поле не порожнє.
Олександр Варвейк

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.