¿Cómo obtener instancia de entidad referenciada?


35

Tengo un objeto de nodo con un campo de imagen llamado field_image. Cuando lo hago

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

Obtengo una matriz con algunas propiedades en lugar del objeto de entidad. La matriz se ve así:

'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

¿Tengo que cargar manualmente la entidad de archivo usando target_ido hay una manera de obtener automáticamente el objeto de entidad referenciado de la instancia de Drupal\image\Plugin\Field\FieldType\ImageItem?

¿Por qué la entidad referenciada no es accesible a través de getter? Podría tener una carga lenta si no está disponible de inmediato.


$ node-> get ('imagefield') -> first () -> getTarget () si solo hay un elemento o $ node-> get ('imagefield') -> referencedEntities () ... en realidad ese último es todo lo que necesita.

@IvanJaros no exactamente: PHP Fatal error: Call to undefined method Drupal\image\Plugin\Field\FieldType\ImageItem::getTarget(). Sin embargo $node->get('imagefield')->referencedEntities()funciona gracias al hecho de que $node->get('imagefield')devuelve la instancia de la EntityReferenceFieldItemListcual implementa el referencedEntities()método. Por lo tanto, su solución es solo parcial: funciona para listas pero no para campos individuales.
SiliconMind

Sí, claro, getTarget está en el tipo de datos de referencia de la entidad, no en el elemento de campo.

Respuestas:


63

El camino a la entidad referenciada es muy largo:

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

Por supuesto, todavía se puede obtener a través de una llamada de línea, pero aún así, es engorroso y me pregunto por qué EntityReferenceItemno proporciona un método que devuelva el objeto de entidad de referencia.

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

También vale la pena señalar que es bastante fácil obtener una matriz de todas las entidades referenciadas:

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

Funciona porque para los campos de referencia de entidad $node->get($field)devuelve una instancia de la EntityReferenceFieldItemListcual implementa el referencedEntities()método.


33

Puedes usar:

$node->field_image->entity

si quieres el primer valor


99
Por eso los métodos mágicos son malos. No hay forma de documentar esto en código y no hay forma de resolver esto mirando las interfaces implementadas.
SiliconMind

66
Es difícil documentar en el código puede ser, pero no es documentación: wizzlern.nl/sites/wizzlern.nl/files/artikel/... . Debido a la estructura dinámica, los métodos realmente no funcionarían mejor, no puedes averiguar con qué clase estás trabajando exactamente ya que todo se construye de forma dinámica. Puede ser difícil de encontrar por primera vez, pero es bastante fácil de recordar una vez que lo hiciste.
Berdir

1
Hay drupal.org/project/agcobcau que ayudará con la finalización automática en IDEs
larowlan

11
@ Berdir Entiendo eso, sin embargo, este sigue siendo un mal diseño. Mira esto: $node->get('field_image')->entitydevuelve la Fileentidad. Sin embargo, $node->get('field_image')->getEntity()devuelve la Nodeentidad principal ! Entiendo que los métodos mágicos pueden ser utilizables, pero son PITA en proyectos más grandes. ¿Por qué molestarse en escribir interfaces y código oo si se nos anima a usar magia de todos modos? Escribiste que es bastante fácil de recordar una vez que lo hiciste , no estoy de acuerdo. Una vez que comience a hacer esto, desarrollará un hábito realmente malo que hará que su código sea menos legible y menos mantenible.
SiliconMind

44
Voto negativo Solía ​​hacerlo de esta manera. Sin embargo, esto a veces se romperá si las referencias de la entidad no se han cargado antes (el resultado será una matriz con target_id en lugar de una entidad instanciada). El método descrito por SiliconMind manejará adecuadamente todos los casos y siempre devolverá una clase de entidad instanciada si el campo no está vacío.
Alexander Varwijk

8

Lo que funcionó para mí fue:

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

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

Las otras respuestas no produjeron la matriz de campos de entidad que esperaba


8

Para saber cómo obtener una entidad de un campo referenciado. Estoy de acuerdo con @SiliconMind sobre entidades referenciadas, devuelve una matriz de objetos de entidad con clave por deltas de elementos de campo.

Así de simple:

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

EntityReferenceFieldItemList :: referencedEntities

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.