Image()->url only coming up broken

I’ve created this blueprint called amenities.yml:

title: Amenities

  draft: true
  listed: true

  url: false
  delete: false

    label: Main Title
    type: text
    width: 1/2

    label: Text
    type: textarea
    width: 1/2

    label: Left Image
    type: files
    query: page.images
    max: 1
    width: 1/2

    label: Right Image
    type: files
    query: page.images
    max: 1
    width: 1/2

and I’ve linked it to a template called amenities.php like so:

<div class="columns">
  <div class="column">
   <div class="about-img"><img src="<?= $page->leftimage()->url() ?>"></div>

  <div class="column">
  <div class="about-img"><img src="<?= $page->rightimage()->url() ?>"></div>

However the image url comes up broken. When I inspect, it shows up as:
<img src="- 2_amenities_1.jpg">

What’s going on?

If you call the url() method on a field, it just turns what is stored in the field into a Url (although you don’t get an Url, hm).

To get the Url of the image, you need to convert it to a file object first:

<?php if ($leftImage = $page->leftimage()->toFile()): ?>
   <div class="about-img"><img src="<?= $leftImage->url() ?>"></div>
<?php endif ?>

Same for the other image.

Within the if-statement we do three things at the same time:

  • we convert the field value into a file object using the toFile() method
  • we assign the result to a variable
  • we check if what we assigned to the variable is an object or null/false

The if statement is necessary because we trust that what the reference we stored in the field is still pointing to a file (the file might have been deleted or renamed later).

Now I’m getting an error “Function Name must be a string”

Also I used url() on a different template as is and it worked fine. For some reason, the images I upload are not being put into the media folder

When I use other templates, it seems to upload the file and display it just fine. I’m not sure what’s happening in this case.

Sorry, when I modified your code I forgot to remove the parens. Corrected above.

Well, that might have worked when the images are from the same page, but you wouldn’t be able to resize them etc. if you don’t create an object first. The code I posted above is the right way to go about this, not calling the url() field method .

See the documentation on how to use the files field in templates/snippets: