Jak uzyskać instancję odnośnego obiektu?


35

Mam obiekt węzła o nazwie pola obrazu field_image. Kiedy robię

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

Dostaję tablicę z pewnymi właściwościami zamiast obiektu encji. Tablica wygląda następująco:

'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

Czy muszę ręcznie ładować obiekt encji przy użyciu pliku, target_idczy istnieje sposób na automatyczne uzyskanie obiektu encji z instancji Drupal\image\Plugin\Field\FieldType\ImageItem?

Dlaczego przywoływany obiekt nie jest dostępny przez moduł pobierający? Może być leniwie załadowany, jeśli nie jest natychmiast dostępny.


$ node-> get ('imagefield') -> first () -> getTarget () jeśli jest tylko jeden element lub $ node-> get ('imagefield') -> referencedEntities () ... tak naprawdę to ostatni wszystko czego potrzebujesz.

@IvanJaros Niezupełnie: PHP Fatal error: Call to undefined method Drupal\image\Plugin\Field\FieldType\ImageItem::getTarget(). $node->get('imagefield')->referencedEntities()Działa jednak dzięki temu, że $node->get('imagefield')zwraca instancję, EntityReferenceFieldItemListktóra implementuje referencedEntities()metodę. Twoje rozwiązanie jest tylko częściowe - działa na listach, ale nie na pojedynczych polach.
SiliconMind,

Tak, getTarget dotyczy typu danych odniesienia encji, a nie elementu pola.

Odpowiedzi:


63

Ścieżka do encji odniesienia jest bardzo długa:

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

Oczywiście nadal można go uzyskać za pomocą jednego wywołania liniowego, ale nadal jest to kłopotliwe i zastanawiam się, dlaczego EntityReferenceItemnie zapewnia metody, która zwróciłaby obiekt jednostki referencyjnej.

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

Warto również zauważyć, że dość łatwo jest uzyskać tablicę wszystkich odnośnych encji:

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

Działa, ponieważ dla pól odwołania do encji $node->get($field)zwraca instancję, EntityReferenceFieldItemListktóra implementuje referencedEntities()metodę.


33

Możesz użyć:

$node->field_image->entity

jeśli chcesz pierwszą wartość


9
Właśnie dlatego magiczne metody są złe. Nie ma sposobu na udokumentowanie tego w kodzie i nie ma sposobu, aby to rozwiązać, patrząc na zaimplementowane interfejsy.
SiliconMind,

6
Trudno dokumentować w kodzie, ale jest dokumentacja: wizzlern.nl/sites/wizzlern.nl/files/artikel/… . Ze względu na dynamiczną strukturę metody naprawdę nie działałyby lepiej, nie możesz dowiedzieć się, z którą klasą pracujesz dokładnie, ponieważ wszystko jest budowane dynamicznie. Może być trudny do znalezienia po raz pierwszy, ale wystarczy pamiętać.
Berdir

1
Istnieje drupal.org/project/agcobcau, który pomoże w automatycznym uzupełnianiu w IDE
larowlan

11
@Berdir Rozumiem to, jednak wciąż jest to zły projekt. Spójrz na to: $node->get('field_image')->entityzwraca Filebyt. $node->get('field_image')->getEntity()Zwraca jednak Nodejednostkę nadrzędną ! Rozumiem, że magiczne metody mogą być przydatne, ale są PITA w większych projektach. Po co męczyć się pisaniem interfejsów i kodu oo, skoro i tak jesteśmy zachęcani do używania magii? Napisałeś, że raz łatwo to zapamiętać - nie zgadzam się. Kiedy zaczniesz to robić, rozwiniesz naprawdę zły nawyk, który sprawi, że twój kod będzie mniej czytelny i mniej konserwowalny.
SiliconMind

4
Doceniony. Robiłem to w ten sposób. Jednak czasem się to psuje, jeśli odwołania do encji nie były wcześniej ładowane (wynikiem będzie tablica z identyfikatorem target_id zamiast instancji instancji). Metoda opisana przez SiliconMind będzie poprawnie obsługiwać wszystkie przypadki i zawsze zwróci instancję klasy encji, jeśli pole nie jest puste.
Alexander Varwijk,

8

Dla mnie zadziałało:

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

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

Inne odpowiedzi nie wytworzyły tablicy pól encji, której się spodziewałem


8

Aby uzyskać encję z pola, do którego istnieje odwołanie. Im zgadzam się z @SiliconMind w odniesieniu do referencedEntities, zwraca tablicę obiektów encji kluczowanych przez delty elementów pola.

Poprostu:

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

EntityReferenceFieldItemList :: referencedEntities

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.