Block error: "Call to undefined function isNotEmpty()" in block type: "image"

Hello :wave:
I build a custom block that renders an HTML <picture>-element using a large list of images in different sizes and for light and dark mode. I am running into a behavior I don’t understand.

The Problem

What should happen

The code (see below) tests if a field is empty. If the field is empty, it does nothing. If the field is not empty, it renders an HTML <source>-element linking to the file referenced in the field.

What actually happens

If the field is empty, the code works. If the field references an image, an error message is displayed:

Block error: “Call to undefined function isNotEmpty()” in block type: “image”

How I interpret this

If the field is empty, Kirby correctly evaluates the field to be empty. If the field contains data, Kirby tries to call isNotEmpty() on the field, which fails. A field that contains data seems not to support testing if it is empty.

The Block / Details

How I structured the block — files

site:
    blueprints:
        blocks:
            image.yml
    snippets:
        blocks:
            image.php

image.php | Snippet

I shortened this excerpt, it causes the same error.

<picture <?= ($block->class()->isNotEmpty()) ? "class='" . preg_replace("/, /", " ", $block->class()) . "'" : "" ; ?>>

	<?php
		//Line Below causes error if certain conditions are met:
		if($block->imageMobileDark()->isNotEmpty()) :

			//Line Below causes error if certain conditions are met:
			$srcset = ($block->imageMobileHiDPIDark()-isNotEmpty()) ? $block->imageMobileHiDPIDark()->toFile()->url() . " 3x, " : "";
			$srcset .= $block->imageMobileDark()->toFile()->url() . " 1x";

	?>

	<source media="(max-width: 413px) and (prefers-color-scheme: dark)" srcset="<?= $srcset ?>" />

	<?php
		endif;
	?>

	<img
		<?= ($block->class()->isNotEmpty()) ? "class='" . preg_replace("/, /", " ", $block->class()) . "'" : "" ; ?>
		alt="<?= $block->alt() ?>"
		src="<?= $block->imageDesktop()->toFile()->url() ?>" />

</picture>

image.yml | Blueprint

Also shortened.

name:
  de: Bild
  en: Image
icon: image
tabs:
  content:
    fields:

      class:
        label:
          de: Layout-Eigenschaften
          en: Layout-Options
        type: multiselect
        options:
          breakout:
            de: Über-Breit
            en: Hero Image
          left:
            de: Linksbündig
            en: Left aligned
          right:
            de: Rechtsbündig
            en: Right aligned
          none:
            de: Volle Breite
            en: Full Width
          floating-illustration:
            de: Illustration
            en: Illustration

      alt:
        label:
          de: Ersatztext
          en: Alt-Text
        type: text

     imageMobileHiDPIDark:
        width: 1/2
        label:
          de: 390w @3x – Nacht
          en: 390w @3x – Night
        type: files
        uploads: image
        min: 0
        max: 1

The complete files

LInk to GitHub commit.

Question

Am I doing something wrong? If so: What should I do differently? If not: Is this a bug?

The problem seems to be the naming of the fields, if you call them all lowercase, it will work:

Note that I wouldn’t check if the field is empty, but if $block->imagemobiledark()->toFile() is an object (i.e. not null). Because even if the field is not empty, the file may still not exist. So isNotEmpty() in the context of fields that are supposed to be converted to objects (users, pages, files) is pretty useless.

$srcset = $block->imagemobiledark()->toFile()?->url() . " 1x";

You’re awesome, thank you! I hadn’t heard of null safe operators before, but doing it this way totally makes sense!

In case somebody runs into the same issue and wants to read up on null safe operators, this page really helped me understand your answer: PHP 8: the null safe operator - stitcher.io

Well, my answer was not so much about the null safe operator, I just added it, because your line of code should have had it to prevent errors.

In most cases, however, you want to check for the image (user, page), in order not to end up with empty HTML tags or for example image tags with empty src attributes (so the usefulness of the null safe operator is limited to certain use cases).

Usually, your code should look something like this (shortened):

<?php if ($image = $block->imagemobiledark()->toFile()): ?>
<picture>
	<source srcset="<?= $image->url() ?>" />
</picture>
<?php endif ?>
2 Likes

Thanks for the helpful answer🙏

I found that the original error was a typo, where $object->function() was written as $object-function() — missing a >. This and your reply made me re-think the whole script, new version has 44 lines of code and works, where the old one had 110 and didn’t. Much better :smile:

1 Like