Problem getting image->url

Hi all

I’m trying to display the first image from a block field as a fallback if the cover image is empty. For some reason the ‘url’ part is not displaying and the is showing up without image path… What am I doing wrong?

<?php elseif ($article->cover()->isEmpty()): ?> 
    <?php $cover_image = $article->text()->toBlocks()->filterBy('type', 'image')->first()->toFile(); ?>
        <figure class="img blog-post" style="--w: 16; --h:9;">
           <img src="<?= $cover_image->url() ?>" class="rounded-4"> 
        </figure>
<?php else: ?>

Because you need to get the image field from that block.

Isnt that what I’m doing?

If I remove the <img src… and just use <?= $cover_image ?> the image is displayed… but I want to use img src to be able to apply a class…

No, you sre trying to vonvert the block to file, not the field inside the block

Okay I’m stuck, any guides on this?

A Block has fields (often many), you need to use toFile() on one of those, not on the Block itself.

Here’s part of your PHP code split on multiple lines to show you what each function call returns:

 $article // the Page 
    ->text() // the text Field
    ->toBlocks() // text Field transformed to blocks Collection
    ->filterBy('type', 'image') // a Collection that only contains image Blocks
    ->first() // the first image Block
    ->toFile(); // a non existing (empty) field with name "toFile"

you see that you are calling ->toFile() on the block itself, but that block contains (in case of the default image block definition) many fields: location, image, src, alt, caption, link, ratio, crop. If you’re using the default image block definition, you need to call toFile on what the ->image() function call returns:

 $article // the Page 
    ->text() // the text Field
    ->toBlocks() // text Field transformed to blocks Collection
    ->filterBy('type', 'image') // a Collection that only contains image Blocks
    ->first() // the first Block of type "image"
    ->image() // ADD THIS; the "image" field of that block
    ->toFile(); // the File object
1 Like

Thank you so much for explaining! I will give this a try. I was thinking of something similar but couldn’t work it out, I was under the impression that filterBy and first would select the first image, but I get where I was wrong now.

Note that if first() doesn’t return a block, calling image will fail.

So use the null-safe operator to prevent errors:

$article // the Page 
    ->text() // the text Field
    ->toBlocks() // text Field transformed to blocks Collection
    ->filterBy('type', 'image') // a Collection that only contains image Blocks
    ->first() // the first Block of type "image"
    ?->image() // ADD THIS; the "image" field of that block
    ->toFile();

Thank you both for the solution but also for explaining!