XF 2.3 Handling null conditionals in template engine

stromb0li

Well-known member
Not sure if this should be a discussion or bug, so please move accordingly.

In 2.2.x I had the following in my template.

HTML:
<xf:option name="option_array[]" value="myvalue" checked="{{ contains($data.items, 'item1') ? 'checked' : '' }}">
   myvalue
</xf:option>

In 2.3.4 I see a type error if $data.items is null, since contains is expecting a value.

Is this a bug where the template engine should check for null values or does the template engine expect types to be strictly enforced (which is what I see in the error) and I should check if the value is null in the condition?

I see the same issue if I did something like {{$myarray.myvalue|to_lower}} and $myarray is null. In 2.2.x this would be valid, but in 2.3, this will result with a type error.
 
Over the years PHP and therefore XF has become a little stricter in terms of type safety. In a lot of cases, for example, passing null into an array or string function could mean a couple of things, maybe you just have no data for some reason and that's expected, or maybe there's some bug in your code where it's null and it shouldn't be. In the latter case, often PHP would have just accepted it and treated it as an empty value, but that could be disguising what could be a real bug.

Therefore, wherever possible, you should be accounting for this in the code.

There's lots of ways to do this. For example if your template code assumes that $data.items should always be available (as it does right now) then maybe whatever code sets $data should ensure items is set to an empty array if it doesn't have a value.

If that's not possible you could wrap some outer code in a conditional, e.g.

Code:
<xf:if is="is_array($data.items)"> ... </xf:if>

Or you could check for null in various ways, but for simplicity here, this is probably a strong contender:

Code:
checked="{{ contains($data.items ?: [], 'item1') ? 'checked' : '' }}"

For this, one {{$myarray.myvalue|to_lower}} you'd probably want something like:

Code:
{{ $myarray.myvalue ? $myarray.myvalue|to_lower : '' }}
 
Back
Top Bottom