如何获取被引用实体的实例?


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是实体引用数据类型,而不是字段项目。

Answers:


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 2016年

11
@Berdir我确实知道,但是这仍然是不好的设计。看一下:$node->get('field_image')->entity返回File实体。但是$node->get('field_image')->getEntity()返回父Node实体!我确实知道魔术方法可能有用,但是在较大的项目中它们是PITA。如果仍然鼓励我们使用魔术,为什么还要编写接口和oo代码呢?您写的很容易记住,一旦您做完 -我不同意。一旦开始执行此操作,您就会养成真正的坏习惯,这会使您的代码可读性和可维护性降低。
SiliconMind

4
不赞成投票。我曾经这样做。但是,如果之前未加载实体引用,则有时会中断(结果将是带有target_id的数组而不是实例化的实体)。SiliconMind概述的方法将正确处理所有情况,并且如果该字段不为空,则将始终返回实例化的实体类。
亚历山大·瓦维克

8

对我有用的是:

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

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

其他答案没有产生我期望的实体字段数组


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.