Get File URI from Media Entity Reference Item in Drupal 8 OR Wrong File Loaded

Another day learning Drupal 8, but today is troubling.

Here's where I'm at. I'm theming search results, and I need to load field values to pass to twig templates—specifically a styled url for img src.

Entities values are not loaded on search results, only little snippets, so I have to load them the hard way, because we want images and nice theming on our search results.

So I started by doing something like this (which is wrong):

    if ($node->hasField('field_primary_image')) {
      if ($img = $node->get('field_primary_image')->first()) {
        if ($file = File::load((int)$img->getString())) {
          $res['img_src'] = ImageStyle::load('media_thumbnail')->buildUrl($file->getFileUri());
        }
      }
    }

But all the images were wrong (said the client). I started checking the media IDs, which I'd assumed were the same as file IDs (as they are in Drupal 7). They matched, but the data being loaded was wrong, really wrong.

Interlude: lay on the floor and stare at the ceiling.

On a swift-following call, a colleague mentions that Media entities have different IDs than File entities.

So I came up with this code:

Edit: I settled upon this code instead of the below.

use Drupal\image\Entity\ImageStyle;
 
$uri = emulsify_return_file_uri_from_entity_ref($node->get('myfield')->first(), 'my_image_style');
 
/**
 * Returns a styled or unstyled img src URL from an image.
 *
 * @param EntityReferenceItem $node targetting an image from $node->get($fieldname)->first()
 * @param String $style_name Optional style name to use. File URI returned if not
 * @return String URI, styled or unstyled, for use as img src
 */
function emulsify_return_file_uri_from_entity_ref($entity_ref_item, $style_name = NULL) {
  if ($media_entity = $entity_ref_item->get('entity')->getTarget()) {
    if ($img_entity = $media_entity->get('field_image')->first()) {
      if ($file_entity = $img_entity->get('entity')->getTarget()) {
        if (!empty($style_name)) {
          return ImageStyle::load($style_name)
                           ->buildUrl($file_entity->get('uri')
                                                  ->first()
                                                  ->getString());
        }
        else {
          return file_create_url($file_entity->get('uri')->getString());
        }
      }
    }
  }
  return NULL;
}

That's verbose. Like asking Borges for a book from his library.

So, Node gets an Entity Reference List gets an Entity Reference Item gets a Media Entity gets an Image Entity Reference gets an Image Entity Reference Item gets an Image Field List gets and Image Field List Item gets a File gets a URI field list gets a URI item gets a URI value.

Surely there must be a simpler way? I looked through all the methods and tried any likely ones...

About the Author

Hi. My name is Jeremiah John. I'm a sf/f writer and activist.

I just completed a dystopian science fiction novel. I run a website which I created that connects farms with churches, mosques, and synagogues to buy fresh vegetables directly and distribute them on a sliding scale to those in need.

In 2003, I spent six months in prison for civil disobedience while working to close the School of the Americas, converting to Christianity, as one does, while I was in the clink.