It seems like not every page has an image.
The call to $page->image()
returns null
when Kirby doesn’t find any image in the page.
Think of null
as “nothing”: you can’t get anything out of nothing, and trying to access methods or properties (in this case url()
) on null
therefore causes this error. Which makes sense, because you can’t have an URL to an image that doesn’t exist.
The solution to the problem is checking if the image actually exists, before trying to construct the <img>
tag:
<?php if($page->image() !== null): ?>
<img <?= attr([
'src' => $page->image()->url(),
'alt' => $page->alt()
]) ?>>
<?php endif ?>
by surrounding the html code of the image with an if statement which checks whether the image actually exists, you avoid calling ->url()
on null
, because that code is never executed when $page->image()
is null
.
The above code however isn’t ideal, because we call $page->image()
twice, once only to check what it returns (in the if statement), and once because we actually want to use its return value.
Since we probably want to avoid calling $page->image()
twice (Kirby has to do some work to find that image), you can also assign the image to a local variable, so you remember it:
<?php
$image = $page->image();
if($image !== null):
?>
<img <?= attr([
'src' => $image->url(),
'alt' => $page->alt()
]) ?>>
<?php endif ?>
That php block with the if statement has become a bit cumbersome, to make it shorter, you can also assign the variable and check if it’s null, all in one line, by taking advantage of the fact that in PHP “the result of any assignment operation is the value that has been assigned: ($a = $b) === $b”:
<?php if(($image = $page->image()) !== null): ?>
Notice the parentheses around the “assignment”. That’s better, but a bit ugly.
We can also exploit PHPs “implicit type coercion”: the if statement expects to get a boolean value (either true
or false
), so it converts any other value type it receives to one of those, essentially by guessing the developers intention. There are rules to this madness, but for us it suffices to know that null
is converted (coerced) to false
, and an image is coerced to true
, therefore we can give the if statement the potential image itself:
<?php if($image = $page->image()): ?>
And this is also the form you normally see in the Kirby docs