I have a working preprocess function that allows me to grab an image for use as a background in the page template from a node if the field exists. It falls back on a default image if supplied, the function looks like this:

 * Implements hook_preprocess_page() for page.html.twig.
function mymodule_preprocess_page(array &$vars) {

  // Preprocess the hero image if it exists (it should on all nodes).
  if (isset($vars['node']->field_hero)){
    $field_hero = $vars['node']->get('field_hero')->getValue();

    // If a file has been uploaded, get it.
    if (!empty($field_hero)){
      $hero_id = $field_hero[0]['target_id'];
      $file = File::load($hero_id);

    // Otherwise get the default if there is one.
    } else {
      $default_image = $vars['node']->getFields()['field_hero']->getFieldDefinition()->getSetting('default_image');
      $file = Drupal::service('entity.repository')->loadEntityByUuid('file', $default_image['uuid']);

    // If a file has been found (there might not be a default), get its path.
    if ($file){
      $path = $file->getFileUri();
      $vars['hero'] = ImageStyle::load('hero_image')->buildUrl($path);


Finding the default file is a convoluted mess of steps that requires loading all of the fields... there has got to be a better way to do this. Is there?


You don't need to load all the fields, you can just load the image field:

$uuid = $vars['node']->get('field_hero')->getFieldDefinition()->getSetting('default_image')['uuid'];
$file = \Drupal::service('entity.manager')->loadEntityByUuid('file', $uuid);

On a different note, the first line of your code assumes that $vars['node'] exists, which it won't on non-node pages, so you should change it to:

if (isset($vars['node'], $vars['node']->field_hero))
  • Thanks for the input. Unfortunately there is no such method as Node::getField, and $vars['node']->get('field_hero') returns NULL if there's nothing in the field. Error msg was PHP Fatal error: Call to undefined method Drupal\\node\\Entity\\Node::getField()
    – Darvanen
    Jan 11 '17 at 2:44
  • Sorry, that's what I get for typing without first checking. I just did a quick test and edited my code. You can use what I have got above to load the file entity.
    – Jaypan
    Jan 11 '17 at 3:07
  • Yeah I tried that, but as I mentioned the equivalent of your code $vars['node']->get('field_image_image') returns nothing unless I've actually uploaded an image on the node.
    – Darvanen
    Jan 11 '17 at 7:07
  • It's working for me, so I don't know what to say. You didn't use field_image_image directly as-is did you? You need to replace that with field_hero like in your code.
    – Jaypan
    Jan 11 '17 at 8:51
  • Edited my code to use field_hero just in case.
    – Jaypan
    Jan 11 '17 at 8:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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