5

I want to print the default image of a node field into the page.html.twig template file in Drupal 8. On doing my research the easiest approach I could find was

{% if node.field_image.entity %}
   <img src="{{ file_url(node.field_image.entity.uri.value) }}"
        alt="{{ node.field_image.alt  }}"
        {% if node.field_image.title %}
        title="{{ node.field_image.title }}"
        {% endif %}
   />
{% endif %}

This works if I load an image in the field but not otherwise with the default image of the image field. I want to use the above code to print the default image that I pick for this image field. Currently the above method gives <img src="http://example.com/" alt=""> for the default image

How can I access the uri value of the default image in the src of the image tag above. Is there any other way to print the default image of a node in the page.htm.twig preferably from within the template layer as I don't have any experience with preprocess functions etc.? My objective is to have a static image which is the same throughout the content type.

0

3 Answers 3

10

Here's one approach, using a helper method. It assumes you have access to the loaded node entity ($entity), and would like to get either the set, or default image for a given image field. I've also left comments and links that explain why Drupal::service('entity.repository') is being used, and how I discovered the way in which the Image module loads the default image settings.

    /**
 * Get the set or default image uri for a file image field (if either
 * exist).
 * @param $entity
 * @param $fieldName
 * @return null|string
 */
function get_image_uri($entity, $fieldName) {
  $image_uri = NULL;
  if( $entity->hasField($fieldName) ) {
    try {
      $field = $entity->{$fieldName}; //Try loading from field values first.
      if ($field && $field->target_id) {
        $file = File::load($field->target_id);
        if ($file) {
          $image_uri = $file->getFileUri();
        }
      }
    } catch (\Exception $e) {
      \Drupal::logger('get_image_uri')->notice($e->getMessage(), []);
    }

    // If a set value above wasn't found, try the default image.
    if (is_null($image_uri)) {
      try {
        $field = $entity->get($fieldName); // Loading from field definition
        if ($field) {
          // From the image module /core/modules/image/ImageFormatterBase.php
          // $default_image = $test->fieldDefinition->getFieldStorageDefinition()->getSetting('default_image');
          $default_image = $field->getSetting('default_image');
          if ($default_image && $default_image['uuid']) {
            // $defaultImageFile = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']));
            // See https://www.drupal.org/node/2549139  entityManager is deprecated.
            // Use entity.repository instead.
            $entityrepository = Drupal::service('entity.repository');
            $defaultImageFile = $entityrepository->loadEntityByUuid('file', $default_image['uuid']);
            if($defaultImageFile) {
              $image_uri = $defaultImageFile->getFileUri();
            }
          }
        }
      } catch (\Exception $e) {
        \Drupal::logger('get_image_uri')->notice($e->getMessage(), []);
      }
    }
  }

  return $image_uri;
}
3
  • I get a Error: Class 'File' not found in get_image_uri() for when the field has a value and $default_image['uuid'] is empty when I have a default image Jul 11, 2016 at 15:12
  • 1
    File::load should be replace by \Drupal\file\Entity\File::load Jul 11, 2016 at 15:37
  • Many thanks, it was really helpful. Regarding the $file = File::load stuff, you can remove many lines by just doing $entity->{$fieldName}->entity->getFileUri();
    – Baud
    Jul 24, 2016 at 20:08
2

Thanks @Blue Waters for the code snippet. I have used it in a preprocess function to integrate with the theme. Sharing my code here, so it helps someone else save some time.

I have a field names field_images, which I'm rendering in the template page.html.twig. The default image properties uui, height & width are readily available in the field settings, so I thought adding the fileuri there would be the simplest approach.

My function in mytheme.theme

function theme_preprocess_page(&$variables) {
  if (array_key_exists('node', $variables)) {
    $node = $variables['node'];

    if (isset($node) && !is_string($node)) {
      if ($node->hasField('field_images')) {
        $images = $node->get('field_images');

        if (sizeof($images) === 0) {
          $image = $images->getFieldDefinition();
          $defaultImage = $image->getSetting('default_image');

          $entityrepository = Drupal::service('entity.repository');
          $defaultImageFile = $entityrepository->loadEntityByUuid('file', $defaultImage['uuid']);

          if($defaultImageFile) {
            $defaultImageUri = $defaultImageFile->getFileUri();
            $defaultImage['fileuri'] = $defaultImageUri;
            $image->setSetting('default_image', $defaultImage);
          }
        }
      }
    }
  }
}

Then in page.html.twig I have the following:

{% if node.field_images is not empty %}
  {% for image in node.field_images %}
    <img src="{{ file_url(image.entity.fileuri) }}" width="{{ image.width }}" height="{{ image.height }}" alt="{{ image.alt }}">
  {% endfor %}
{% else %}
  {% set image = node.field_images.setting('default_image') %}
  <img src="{{ file_url(image.fileuri) }}" width="{{ image.width }}" height="{{ image.height }}" alt="{{ image.alt }}">
{% endif %}
-1

Worked around it by using static images instead of default images with the code {{ base_path ~ directory }} to get path to image (src) without any preprocessing.

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.