Working with Media items in code

When working with media items rather than file fields, getting image data is just a little more complicated. You'll need to get the image details through the media item entity, rather than directly through the field. In this example, we'll look at preprocessing a media image reference field in a paragraph to get the original URL instead of a fully rendered image.

Get media image URL

Getting the raw URL of an image is something we do often, whether it's to use in CSS for a background image, or passing to a data attribute for rendering. There is just one extra step for this when preprocessing a media item instead of an image field.

function theme_preprocess_paragraph(&$variables) {
  $paragraph = $variables['paragraph'];

  if ($paragraph->hasField('field_image') && !$paragraph->get('field_image')->isEmpty()) {
    $image_entity = $paragraph->get('field_image')->entity;
  
    $image_uri = $file_entity->get('field_media_image')->entity->getFileUri();

    if (!empty($image_uri)) {
      $image_url = file_create_url($file_uri);
      $variables['image_url'] = $image_url;
    }
  }
}

Rendering Responsive Images

Sometimes when building a page we want to have a background image behind our content, but it also needs to adapt to the viewport size so we aren't showing a 1920x1080px image on mobile devices. To do that, we often render a responsive image and position it behind the content using CSS. If you can't accomplish this with view display and twig templating easily, below is an example of how you can render it in a preprocess function:

function theme_preprocess_paragraph(&$variables) {
  $paragraph = $variables['paragraph'];
  $responsive_image = NULL;

  if ($paragraph->hasField('field_background_image') && !$paragraph->get('field_background_image')->isEmpty()) {
    $image_field  = $paragraph->get('field_background_image');
    $image_entity = $image_field->entity;
    $image_style  = 'default_style';

    // Set display options.
    $display_options = [
      'label' => 'hidden',
      'type' => 'responsive_image',
      'settings' => [
        'responsive_image_style' => $image_style,
      ],
    ];

    // Get image, apply display options.
    if ($image_entity && !$image_entity->get('field_media_image')->isEmpty()) {
      $responsive_image = $image_entity->get('field_media_image')->view($display_options);
    }

    $variables['responsive_image'] = $responsive_image;
  }
}

You can use the same code, but omit the $display_options variable to render a media item using it's default display settings. This also works for other entities like nodes (another post!).

Posted April 6th, 2020
Tested againstDrupal 8.8.4