3

I have a preprocess function that I am using to grab one of 3 profile images. Basically we're replacing a couple stand-alone image fields with a media library reference field. The goal is to display the media library image if it is populated at a particular style (called '65x65') or fall back to other stand-alone legacy image fields if it is not populated.

I'm having a heck of a time building the media library image url. I have tried quite a few things based on this discussion and this discussion and others. The image field on the image media type is called field_media_image (screenshot)media image setup. I'm not sure if it's useful to post my half-baked code attempts so I will leave the parts that I know are working.

foreach ($block->field_block_contributors->referencedEntities() as $contributor) {
    # prefer the media library reference profile image if it exists

    if (!$contributor->field_profile_image->isEmpty()) { # check if there is a media library profile image

      $my_profile_image = $contributor->get('field_profile_image')->referencedEntities(); # seems to load this field ok
      if (!empty($my_profile_image)) {
      // kint($my_profile_image);
      # load a media library image using the '65x65' image style
      // $styled_image_url = ??????


      }
    } elseif (!$contributor->field_user_image->isEmpty()) { # or fall back to one of two legacy image fields.  This part works
      $styled_image_url = ImageStyle::load('65x65')->buildUrl($contributor->field_user_image->entity->getFileUri());
    } elseif (!$contributor->field_speaker_image->isEmpty()) {
      $styled_image_url = ImageStyle::load('65x65')->buildUrl($contributor->field_speaker_image->entity->getFileUri());
    } else {
      $styled_image_url = '';
    }
    $variables['profiles'][] = [
      'title' => $contributor->field_user_title->value,
      'link' => "/user/" . $contributor->uid->value,
      'image' => ['src' => $styled_image_url, 'attributes' => $contributor->field_user_image->value],
      'name' => $contributor->field_user_first_name->value . " " . $contributor->field_user_last_name->value,
    ];
  }

PS. Bonus beer for anyone who knows off the top of their heads how I can link to the user's name instead of their user id # ( the line 'link' => "/user/" . $contributor->uid->value, ) Thanks!!!

4
  • What is field_profile_image? Is this the entity reference to the media entity? Then you could go the same as with the other fields by $my_profile_image->field_media_image. What do you mean about "if it is populated at a particular style"? If the image and style exists Drupal "populates" it for you if you do it the right way. I would recommend you to get a little more in touch with Drupal rendering and display view modes. This code seems to go away (probably unnecessarily) from "Drupal patterns". Commented Mar 18, 2021 at 6:14
  • To answer the Bonus question: To get a URL string
    – No Sssweat
    Commented Mar 18, 2021 at 6:28
  • Yes, field_profile_image is an entity reference field from the user to the media library image. So field_profile_image is a custom field for the user. (see screenshot for user fields here i.imgur.com/RkqrMAA.png ). Sorry I did not explain that well at all. I'm simply trying to find the url to the referenced image and display it at the existing "65x65" display mode. Yes I am familiar with drupal rendering and display modes and believe I am on the right track here. Thanks for your help!! Commented Mar 18, 2021 at 6:31
  • Oh, so on the bonus question just 'link' => $contributor->toUrl()->toString(), nice one!! Commented Mar 18, 2021 at 7:04

2 Answers 2

4

Maybe not the most elegant solution but I was able to pull it off with...

      if (!$contributor->field_profile_image->isEmpty()) { # check if there is a media library profile image

      $my_image = $contributor->get('field_profile_image')->getValue()[0]['target_id']; # Find ID of media library image
      $media_entity_load = Media::load($my_image); // Loading media entity.
      $uri = $media_entity_load->field_media_image->entity->getFileUri(); // It is for image media.
      $styled_image_url = ImageStyle::load('65x65')->buildUrl($uri); // Here you will get URL of uploaded image.
2

I wrote a little module I found helpful to get the media entity image values.

custom_helper_services/custom_helper_services.info.yml:

name: 'Custom Helper Services'
type: module
description: 'Provides useful services for working with themes.'
core_version_requirement: ^8 || ^9
package: 'Custom'

custom_helper_services/custom_helper_services.module:

<?php

/**
 * @file
 * Contains custom_helper_services.module.
 */

use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Implements hook_help().
 */
function custom_helper_services_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    // Main module help for the custom_helper_services module.
    case 'help.page.custom_helper_services':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('Provides helpful service functions.') . '</p>';
      return $output;

    default:
  }
}

custom_helper_services/custom_helper_services.services.yml:

services:
  chs:
    class: Drupal\custom_helper_services\Services\CustomHelperServices
    arguments: ['@entity_type.manager','@current_route_match','@entity.repository']

custom_helper_services/src/Services/CustomHelperServices.php:

<?php

namespace Drupal\custom_helper_services\Services;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;

/**
 * Class CustomHelperServices.
 *
 * Provides helper services to be used in modules and themes.
 */
class CustomHelperServices {

  /**
   * Entity Type Manager.
   *
   * @var Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Route Match Interface.
   *
   * @var Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Entity Repository Interface.
   *
   * @var Drupal\Core\Entity\EntityRepositoryInterface
   */
  protected $entityRepository;

  /**
   * CustomHelperServices constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   Entity Type Manager.
   * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
   *   The Route Match Interface.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository
   *   The Entity Repository Interface.
   */
  public function __construct(EntityTypeManagerInterface $entityTypeManager, RouteMatchInterface $routeMatch, EntityRepositoryInterface $entityRepository) {
    $this->entityTypeManager = $entityTypeManager;
    $this->routeMatch = $routeMatch;
    $this->entityRepository = $entityRepository;
  }

  /**
   * Build our media style path service.
   */
  public function getMediaFieldImage($mediaField = NULL, $imageStyle = NULL) {

    if ($mediaField && $mediaField->entity) {

      // Get image.
      $mediaImage = $mediaField->entity
        ->get('field_media_image');

      // Get image attributes.
      $alt = $mediaImage->alt;
      $width = $mediaImage->width;
      $height = $mediaImage->height;
      $title = $mediaImage->title;

      // Get image entity.
      $mediaImageEntity = $mediaImage->entity;

      // Get image mime type.
      $mediaImageMimeType = $mediaImageEntity->getMimeType();

      // Get image file URI.
      $mediaImageEntityUri = $mediaImageEntity->getFileUri();

      // Set image URL.
      $url = file_create_url($mediaImageEntityUri);

      // Set image style URL.
      if ($imageStyle && $mediaImageMimeType !== "image/svg+xml") {
        $url = $this->entityTypeManager
          ->getStorage('image_style')
          ->load($imageStyle)
          ->buildUrl($mediaImageEntityUri);
      }

      return [
        'url' => $url,
        'alt' => $alt,
        'width' => $width,
        'height' => $height,
        'mimeType' => $mediaImageMimeType,
        'title' => $title,
      ];
    }

    return NULL;
  }

}

Then in preprocess node, for example, you can call:

$variables['myVariable'] = \Drupal::service('chs')->getMediaFieldImage($node->get("field_name"), "image_style");
// Just need to pass the media field name. The image style is optional.

Then in a Twig template you can access as:

{{ myVariable.url }}
{{ myVariable.alt }}
{{ myVariable.width }}
{{ myVariable.height }}
{{ myVariable.mimeType }}
{{ myVariable.title }}

I've stripped down this code to show just the media entity image get, so let me know if there are issues and I can update if needed.


A shorter version (using preprocess_node()):

use Drupal\image\Entity\ImageStyle;
function MYTHEME_preprocess_node(&$variables) {
  $node = $variables['node'];
  if ($node->hasField('field_name') && $node->get('field_name')->entity) {
    $imageURI = $node->field_name->entity->getFileUri();
    $variables['myVariable'] = ImageStyle::load('image_style')->buildUrl($imageURI);
  }
}

Your Answer

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

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