Skip to content

Conversation

@felds
Copy link

@felds felds commented Dec 1, 2025

Adds native support for Twig’s null-safe ?. operator so templates can traverse objects and arrays without defensive plumbing: {{ user?.address?.city }} now renders the value when present and stays silent when any hop is null.

?. reuses the existing GetAttrExpression operator, so it should have otherwise the same precedence and behavior as ..

Usage cases can be found in the tests:

[
'{{ foo?.bar }}',
['foo' => (object)['bar' => 'baz']],
'baz',
],
[
'{{ foo?.bar }}',
['foo' => null],
'',
],
[
'{{ foo?.bar?.baz }}',
['foo' => (object)['bar' => (object)['baz' => 'qux']]],
'qux',
],
[
'{{ foo?.bar?.baz }}',
['foo' => (object)['bar' => null]],
'',
],
[
'{{ foo?.bar?.baz }}',
['foo' => null],
'',
],
[
'{{ foo?.bar?.baz ?? "qux" }}',
['foo' => null],
'qux',
],
[
'{{ foo?.bar ?? "qux" }}',
['foo' => (object)['bar' => 0]],
'0',
],
[
'{{ foo?.bar ?? "qux" }}',
['foo' => (object)['bar' => false]],
'',
],

Tests cover both the rendered output and the generated PHP.

Let me know if any tests are missing or if the implementation should be done any other way.

@felds
Copy link
Author

felds commented Dec 1, 2025

This should fix issue #3260

@felds
Copy link
Author

felds commented Dec 1, 2025

The failing tests are already present in twigphp:3.x. I have no idea what they refer to, and I don't think they are related to the changes in this PR.

@felds
Copy link
Author

felds commented Dec 1, 2025

I've found the bug.

It was not in this repo, but it appeared when symfony/intl had some data updated.

I think testing for exact results from dependencies is not a good idea, since it would require updating the tests in this lib every time the depended package was updated, so I changed the test to expect at least N results instead of exactly N results.

@willrowe
Copy link
Contributor

willrowe commented Dec 1, 2025

This is a duplicate of #4623

@felds
Copy link
Author

felds commented Dec 2, 2025

@willrowe thanks for pointing that out. I wonder why that PR is stuck. It looks pretty good too...

@johndodev
Copy link

up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants