2

What is the difference between using getValue() and referencedEntities() in order to get the paragraph on a node?

See example below. Both examples are used in a node template such as node--page--full.html.twig and mymodule_preprocess_node() hook.

Using getValue()

$paragraph = $node->field_paragraph->getValue();
foreach ( $paragraph as $pr ) {
  // Get the entity using Paragraph::load(entity_id).
  $pr_item = \Drupal\paragraphs\Entity\Paragraph::load($pr['target_id']);

  // Now use $pr_item to get any field.
  $pr_item_img = $pr_item->field_image;
}

Using referencedEntities()

$pr_field = $node->field_paragraph->referencedEntities();
foreach($pr_field as $pr) {
  $item_image = $pr->get('field_image');
}

I am mainly concerned with the following:

  1. What is more performant?
  2. What is the best practice since both work?
  3. Is either method considered a magic method? I ask because you can use $node->field_paragraph as opposed to $node->get('field_paragraph')
3
  • I guess it depends - there are a number of differences. What aspect are you trying to compare specifically? Performance? Best practice? Something else?
    – Clive
    Sep 17, 2018 at 18:28
  • @Clive I have updated the question to be more specific. Sep 17, 2018 at 20:04
  • As I mentioned in the comments of the answer.. See wizzlern.nl/drupal/drupal-8-entity-cheat-sheet. You should almost never need to use getValue(). You can loop over field objects and reference fields have a computed entitty property. foreach ($node->get('field_paragraph') as $item) (without get works too but I prefer using get(), and then it's just $item->entity to get the paragraph, and then you can access its fields.
    – Berdir
    Sep 19, 2018 at 21:59

1 Answer 1

2

Performance

EntityReferenceFieldItemList::referencedEntities performs better because it uses loadMultiple() instead of loading the entities separately.

Best practice

You use static code to load the entity which should be avoided when possible. You could make proper OOP code out of it, but it is also best practice to not reinvent the wheel.

Edit: You've added the info this is in node preprocess. Then best practice would be to render the paragraph field in the node template {{ content.field_paragraph }}. Configure the field in UI, for example add a custom view mode. Theme the output in field and paragraph templates for this specific field or view mode.

Magic method

No, this doesn't involve a magic method, the method is called directly. A magic method is involved in getting entity fields as if they were object properties, like the example you've mentioned $node->field_paragraph.

Translation

You need to translate the entities for both methods before you can output translated field values directly:

$paragraph = \Drupal::service('entity.repository')
  ->getTranslationFromContext($paragraph, $langcode);

By the way core translates the entities later when building the rendered output using the entity reference field formatter. This works for core because it usually doesn't output field values directly, so this could be considered as bad practice as well, see for example this question from today How to display Paragraph bundles fields links inside a page.html.twig file that are within a paragraph bundle in Twig?.

Revisions

Paragraphs are stored in an EntityReferenceRevisions field. Your example code ignores the revision data and so you might load the wrong version. One more reason to use the methods provided by the field, referencedEntities() or $item->entity in case you need to load a single entity.

6
  • referencedEntities unfortunately does not take into account whats the current language of the entity is, so it's usage can be quite annoying on a multilingual site.
    – ssibal
    Sep 18, 2018 at 8:23
  • Note on performance, that might be true for regular entity reference fields, but it's a bit more complicated for paragraphs, those are referenced with a revision ID, there is no load multiple for that and also no cache, I also just realized that we didn't add the optimization that we did to single-loading paragraphs
    – Berdir
    Sep 18, 2018 at 19:42
  • @Berdir, didn't think about this, I've answered more generally for reference fields. For Paragraphs the example code is ignoring target_revision_id, so this is not only a performance question, but how to get the right content.
    – 4uk4
    Sep 18, 2018 at 20:21
  • True, that example snippet is quite wrong and should just use foreach ($field as $item) and then $item->entity. And the second uses confusing variable names, $item is usually used for field item objects, that's actually an entity and should use $paragraph or $entity.
    – Berdir
    Sep 18, 2018 at 21:50
  • 1
    @4k4 we went with the custom view mode method that you suggested under Best practice -- Edit Oct 1, 2018 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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