참조 된 엔터티의 인스턴스를 얻는 방법?


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

를 사용하여 파일 엔티티를 manullay로드해야 합니까? 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')EntityReferenceFieldItemListreferencedEntities()
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
IDE에서 자동 완성을 도와주는 drupal.org/project/agcobcau 가 있습니다
larowlan

11
@ Berdir 나는 이해하지만, 이것은 여전히 ​​나쁜 디자인입니다. 이것을보십시오 : 엔티티를 $node->get('field_image')->entity반환합니다 File. 그러나 $node->get('field_image')->getEntity()부모 Node엔터티를 반환합니다 ! 마법 방법을 사용할 수는 있지만 더 큰 프로젝트에서는 PITA입니다. 어쨌든 마술을 사용하도록 장려하면 왜 인터페이스와 oo 코드를 작성해야합니까? 당신은 당신이 한 번 기억하기 쉽다고 썼다 -나는 동의하지 않는다. 이 작업을 시작하면 코드를 읽기 어렵고 유지 관리하기 어려워지는 나쁜 습관이 생깁니다.
SiliconMind

4
공감. 나는 이런 식으로 그것을 사용했다. 그러나 엔티티 참조가 이전에로드되지 않은 경우 때때로 중단됩니다 (결과는 인스턴스화 된 엔티티 대신 target_id가있는 배열입니다). SiliconMind에 의해 요약 된 메소드는 모든 경우를 올바르게 처리하며 필드가 비어 있지 않으면 항상 인스턴스화 된 엔티티 클래스를 리턴합니다.
Alexander Varwijk

8

나를 위해 일한 것은 다음과 같습니다.

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

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

다른 답변은 내가 기대했던 엔티티 필드 배열을 생성하지 못했습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.