Come ottenere l'istanza dell'entità referenziata?


35

Ho un oggetto nodo con campo immagine chiamato field_image. Quando io faccio

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

Ottengo matrice con alcune proprietà anziché oggetto entità. L'array è simile al seguente:

'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

Devo caricare manualmente l'entità file usando target_ido c'è un modo per ottenere automaticamente l'oggetto entità referenziato dall'istanza di Drupal\image\Plugin\Field\FieldType\ImageItem?

Perché l'entità referenziata non è accessibile tramite getter? Potrebbe essere lento se non è disponibile immediatamente.


$ node-> get ('imagefield') -> first () -> getTarget () se esiste solo un elemento o $ node-> get ('imagefield') -> referencedEntities () ... in realtà l'ultimo è tutto ciò di cui hai bisogno.

@IvanJaros Non esattamente: PHP Fatal error: Call to undefined method Drupal\image\Plugin\Field\FieldType\ImageItem::getTarget(). Tuttavia $node->get('imagefield')->referencedEntities()funziona grazie al fatto $node->get('imagefield')restituisce istanza di EntityReferenceFieldItemListquale implementa il referencedEntities()metodo. Quindi la tua soluzione è solo parziale: funziona per elenchi ma non per singoli campi.
SiliconMind

Sì giusto, getTarget è sul tipo di dati di riferimento dell'entità, non sull'elemento di campo.

Risposte:


63

Il percorso verso l'entità referenziata è molto lungo:

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

Ovviamente uno può ancora ottenerlo tramite una chiamata di linea, ma è comunque ingombrante e mi chiedo perché EntityReferenceItemnon fornisca un metodo che restituisca l'oggetto entità di riferimento.

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

Vale anche la pena notare che è abbastanza facile ottenere una matrice di tutte le entità referenziate:

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

Funziona perché per i campi di riferimento dell'entità $node->get($field)restituisce un'istanza di EntityReferenceFieldItemListcui implementa il referencedEntities()metodo.


33

Puoi usare:

$node->field_image->entity

se vuoi il primo valore


9
Ecco perché i metodi magici sono cattivi. Nessun modo per documentarlo nel codice e nessun modo per capirlo guardando le interfacce implementate.
SiliconMind,

6
E 'difficile da documentare nel codice forse, ma non v'è documentazione: wizzlern.nl/sites/wizzlern.nl/files/artikel/... . A causa della struttura dinamica, i metodi non funzionerebbero davvero meglio, non puoi capire con quale classe stai lavorando esattamente dato che tutto è costruito insieme in modo dinamico. Potrebbe essere difficile da trovare per la prima volta, ma è abbastanza facile da ricordare una volta fatto.
Berdir,

1
C'è drupal.org/project/agcobcau che aiuterà con il completamento automatico negli IDE
larowlan

11
@Berdir Lo capisco, tuttavia questo è ancora un cattivo design. Guarda questo: $node->get('field_image')->entityrestituisce Fileentità. Tuttavia $node->get('field_image')->getEntity()restituisce Nodeentità padre ! Capisco che i metodi magici potrebbero essere utilizzabili, ma sono PITA in progetti più grandi. Perché preoccuparsi di scrivere interfacce e codice oo se siamo comunque incoraggiati a usare la magia? Hai scritto che è abbastanza facile da ricordare una volta fatto : non sono d'accordo. Una volta che inizi a fare questo, svilupperai un'abitudine davvero cattiva che renderà il tuo codice meno leggibile e meno gestibile.
SiliconMind

4
Downvoted. Lo facevo in questo modo. Tuttavia, questo a volte si interromperà se i riferimenti alle entità non sono stati caricati prima (il risultato sarà una matrice con target_id anziché un'entità istanziata). Il metodo descritto da SiliconMind gestirà correttamente tutti i casi e restituirà sempre una classe di entità istanziata se il campo non è vuoto.
Alexander Varwijk,

8

Ciò che ha funzionato per me è stato:

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

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

Le altre risposte non hanno prodotto l'array di campi di entità che mi aspettavo


8

Per come ottenere un'entità da un campo di riferimento. Sono d'accordo con @SiliconMind in merito a referencedEntities che restituisce una matrice di oggetti entità codificati da delta di elementi di campo.

Semplice:

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

EntityReferenceFieldItemList :: referencedEntities

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.