37

I have a node object with image field named field_image. When I do

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

I get array with some properties instead of entity object. The array looks like this:

'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

Do I have to manullay load the file entity using target_id or there is a way to automatically get referenced entity object from instance of Drupal\image\Plugin\Field\FieldType\ImageItem?

Why the referenced entity is not accessible via getter? It could be lazy loaded if it's not available immediately.

  • $node->get('imagefield')->first()->getTarget() if there is only one item or $node->get('imagefield')->referencedEntities() ... actually that last one is all you need. – user21641 Jan 10 '16 at 14:52
  • @IvanJaros Not exactly: PHP Fatal error: Call to undefined method Drupal\image\Plugin\Field\FieldType\ImageItem::getTarget(). However $node->get('imagefield')->referencedEntities() works thanks to the fact $node->get('imagefield') returns instance of EntityReferenceFieldItemList which implements referencedEntities() method. So your solution is only partial - it works for lists but not for single fields. – SiliconMind Jan 10 '16 at 15:18
  • Yeah right, the getTarget is on entity reference data type, not field item. – user21641 Jan 10 '16 at 15:23
72

The path to referenced entity is very long:

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

Of course one can still get it via one liner call, but still, it is cumbersome and I wonder why EntityReferenceItem does not provide method that would return the reference entity object.

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

It's also worth noting that it's quite easy to get array of all referenced entities:

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

It works because for entity reference fields $node->get($field) returns instance of EntityReferenceFieldItemList which implements referencedEntities() method.

| improve this answer | |
32

You can use:

$node->field_image->entity

if you want the first value

| improve this answer | |
  • 9
    This is why magic methods are bad. No way to document this in code and no way to figure out this by looking at implemented interfaces. – SiliconMind Jan 10 '16 at 20:33
  • 6
    It's hard to document in code maybe, but there is documentation: wizzlern.nl/sites/wizzlern.nl/files/artikel/…. Due to the dynamic structure, methods wouldn't really work better, you can't figure out which class you're working with exactly as everything is built together dynamically. It might be hard to find for the first time, but it's easy enough to remember once you did. – Berdir Jan 10 '16 at 21:17
  • 1
    There is drupal.org/project/agcobcau which will help with auto completion in IDEs – larowlan Jan 10 '16 at 23:03
  • 13
    @Berdir I do understand that, however this is still bad design. Look at this: $node->get('field_image')->entity returns File entity. However $node->get('field_image')->getEntity() returns parent Node entity! I do understand that magic methods might be usable, but they are PITA in larger projects. Why bother writing interfaces and oo code if we are encouraged to use magic anyway? You wrote it's easy enough to remember once you did - I disagree. Once you start doing this, you'll develop really bad habit that will make your code less readable and less maintainable. – SiliconMind Jan 11 '16 at 8:44
  • 4
    Downvoted. I used to do it this way. However this will sometimes break if the entity references haven't been loaded before (the result will be an array with target_id instead of an instantiated entity). The method outlined by SiliconMind will properly handle all cases and will always return an instantiated entity class if the field is not empty. – Alexander Varwijk Nov 20 '17 at 15:09
12

For how to get an entity from a referenced field. Im agree with @SiliconMind about referencedEntities it return an array of entity objects keyed by field item deltas.

Just simple:

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

EntityReferenceFieldItemList::referencedEntities

| improve this answer | |
  • This is indeed a very clear way to do this, and code is self explanatory. Until I read your anwer, I was doing $term_id = $productAttributeValue->get('field_product_attribute_statut')->getValue()[0]['target_id']; which works but is awful :-) – Kojo May 14 at 14:39
7

What worked for me was:

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

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

The other answers didn't produce the entity fields array I was expecting

| improve this answer | |
0

$ENTITY->FIELD_MACHINE_NAME->entity returns the first item that referenced. but if you want to get value of the specified field in that entity use

$ENTITY->FIELD_MACHINE_NAME->entity->FIELDMACHINENAME_IN_REFERENCED_ENTITY->value

for example, if you want to get hospital_key of the hospital entity reference field on user entity. use

$user->field_hospital->entity->field_hospital_key->value
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.