Skip to content

[ExpressionLanguage] Add support for null-safe operator #45795

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

mytuny
Copy link
Contributor

@mytuny mytuny commented Mar 20, 2022

Q A
Branch? 6.1
Bug fix? no
New feature? yes
Deprecations? no
Tickets Fix #45411, #21691
License MIT
Doc PR symfony/symfony-docs#16630

This is a long-time-lasting feature for the ExpressionLanguage component. I've been waiting for the support of Nullsafe operator in expressions dealing with mutable objects, until I finally decided to work on it once for all 👍

The lack of nullsafety feature has been repeatedly reported as a BUG several time (e.g #45411 & #21691) when it is actually a missing feature.

Currently, expressions like foo.bar assumes that the property bar "always" exists on the object foo and if doesn't the parser throws a RuntimeException. Although, sometimes, that's exactly the behavior we need, some other times we may work with mutable objects with uncontrolled structure, thus, such assumption is error-prone and will force adding extra checks making the expression uglier and less readable.

The proposed work, introduces the support for the ?. syntax alongside with the usual . syntax to help working with objects with dynamic structure. The two notations works identically in all normal cases. The difference occurs when trying to access non-existant properties and/or methods where the . notation will throw a RuntimeException as usual and the ?. notation will return null instead and no errors nor exceptions will be thrown. Hence the name "Null-Safe".

PS: This work account ONLY for accessing object's properties and methods. It does not account for non-existant array items which is a seperate problem that can be addressed by introducing the null coalescing operator. Another feature that I'm currently working on as well 💯

@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has a contribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (see https://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (see https://symfony.com/releases)
  • Features and deprecations must be submitted against the 6.1 branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

@carsonbot carsonbot changed the title [ExpressionLanguage] [Feature] Add Support For Nullsafe Operator [ExpressionLanguage] Add Support For Nullsafe Operator Mar 20, 2022
@mytuny
Copy link
Contributor Author

mytuny commented Mar 20, 2022

I start working on this PR before the 6.1 release, therefore, this work is based on branch 5.4 instead.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's great thanks! Here are some minor comments

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Mar 20, 2022

Right, please rebase to target 5.46.1 as that's the branch where new features are merged.

@fabpot
Copy link
Member

fabpot commented Mar 20, 2022

@nicolas-grekas wanted to say 6.1, not 5.4, for the branch :)

@mytuny
Copy link
Contributor Author

mytuny commented Mar 20, 2022

I just rebased to 6.1, however, this seem to pollute the PR commits history :/ + had to resolve few conflits.
Don't you think that is better to re-open a clean PR based on 6.1 branch ?

@stof stof changed the base branch from 5.4 to 6.1 March 21, 2022 11:46
@stof
Copy link
Member

stof commented Mar 21, 2022

@mytuny this polluted it, because you were still targetting the 5.4 branch in the PR. I edited the PR to change the target branch to 6.1, which fixed it.

@stof
Copy link
Member

stof commented Mar 21, 2022

also, it looks like you merged your rebased branch with the upstream branch instead of forcing the push, thus duplicating the commits in the history. See https://symfony.com/doc/current/contributing/code/pull_requests.html#rebase-your-pull-request

@mytuny
Copy link
Contributor Author

mytuny commented Mar 21, 2022

@mytuny this polluted it, because you were still targetting the 5.4 branch in the PR. I edited the PR to change the target branch to 6.1, which fixed it.

Brilliant! Many thanks 👏

@mytuny
Copy link
Contributor Author

mytuny commented Mar 21, 2022

also, it looks like you merged your rebased branch with the upstream branch instead of forcing the push, thus duplicating the commits in the history. See https://symfony.com/doc/current/contributing/code/pull_requests.html#rebase-your-pull-request

Although I followed exactly the steps mentioned there, a conflit-resolving commits that I've added during the rebase of 6.1 has introduced that duplication. The conflits occured with files that have been changed both in 6.1 and in my PR as well comparing to 5.4, namely the CHANGELOG file and the ConstantNode.php file. That's why I asked if it is better to re-submit a PR based on 6.1 right from the start 🤔

@stof
Copy link
Member

stof commented Mar 21, 2022

@mytuny the process I linked to is using a force push, precisely to avoid doing a merge of the remote branch after the rebase.
You should not have the commit Merge remote-tracking branch 'origin/feature_expressionlanguage_nulls at all in your branch.

@mytuny
Copy link
Contributor Author

mytuny commented Mar 21, 2022

Yess, exactly :( any suggestions ?

@stof
Copy link
Member

stof commented Mar 21, 2022

@mytuny use git reset --hard bffdcd22cabac5e105697b44e8e34c080dbe5f39 to reset your branch to the commit before the bad merge, and then actually follow the end of the process as documented

@mytuny mytuny force-pushed the feature_expressionlanguage_nullsafe branch from 97a7c84 to bffdcd2 Compare March 21, 2022 15:18
@mytuny
Copy link
Contributor Author

mytuny commented Mar 21, 2022

@stof All right! the hard reset does the trick.
This time I forced the push and we seem to have a cleaner commits history by now...
Thank you :)

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

almost good to me :)

@nicolas-grekas nicolas-grekas changed the title [ExpressionLanguage] Add Support For Nullsafe Operator [ExpressionLanguage] Add support for nullsafe operator Apr 4, 2022
@nicolas-grekas nicolas-grekas force-pushed the feature_expressionlanguage_nullsafe branch from 2363842 to 998d802 Compare April 4, 2022 13:11
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just fixed my own comments and rebased. LGTM 👍

@nicolas-grekas
Copy link
Member

Note that the nullsafe operator only guards against null. It does not guard against undefined properties/keys.

@nicolas-grekas nicolas-grekas force-pushed the feature_expressionlanguage_nullsafe branch from 998d802 to b161f1e Compare April 4, 2022 13:37
@nicolas-grekas nicolas-grekas changed the title [ExpressionLanguage] Add support for nullsafe operator [ExpressionLanguage] Add support for null-safe operator Apr 4, 2022
@nicolas-grekas nicolas-grekas force-pushed the feature_expressionlanguage_nullsafe branch from b161f1e to 946c59f Compare April 4, 2022 13:40
@nicolas-grekas
Copy link
Member

Thank you @mytuny.

@nicolas-grekas nicolas-grekas merged commit 1b75cc0 into symfony:6.1 Apr 4, 2022
@nicolas-grekas
Copy link
Member

Note that the nullsafe operator only guards against null. It does not guard against undefined properties/keys.

About this, we might want to add support for the null-coalescing operator ??, which is able to ignore undefined vars/properties/keys.

@mytuny up to give this a try as a follow up? Please have a look at the changes I made they might help (esp. the part where the lexer is modified);

@mytuny
Copy link
Contributor Author

mytuny commented Apr 4, 2022

Thank you @nicolas-grekas !!
I'm so glad to help improve this incredible project :)

@mytuny
Copy link
Contributor Author

mytuny commented Apr 4, 2022

Note that the nullsafe operator only guards against null. It does not guard against undefined properties/keys.

About this, we might want to add support for the null-coalescing operator ??, which is able to ignore undefined vars/properties/keys.

@mytuny up to give this a try as a follow up? Please have a look at the changes I made they might help (esp. the part where the lexer is modified);

Yup! sure, I'm working on that null-coalescing operator right now. Your comments did and will help me even more to have the feature ready for the next release too.

Thank you once more @nicolas-grekas

javiereguiluz added a commit to javiereguiluz/symfony-docs that referenced this pull request Apr 4, 2022
…tax for accessing object's properties and methods (Sofien NAAS)

This PR was submitted for the 5.4 branch but it was merged into the 6.1 branch instead.

Discussion
----------

[ExpressionLanguage] Add support for Nullsafe syntax for accessing object's properties and methods

[ExpressionLanguage] [NEW FEATURE]

This PR introduces the support for `nullsafe operator` in expressions that works with accessing object's properties and methods.

The proposed change here, includes a paragraph under the sub-page `/expression_language/syntax` to describe the new feature usage. The sub-paragraph has a title of `Nullsafe operator` under the paragraph `Working with Objects`.

The actual work related to this Doc PR available as Symfony PR [#45795](symfony/symfony#45795).

Commits
-------

23bf15d [ExpressionLanguage] Add support for Nullsafe syntax for accessing object's properties and methods.
@fabpot fabpot mentioned this pull request Apr 15, 2022
fabpot added a commit that referenced this pull request Jul 25, 2022
…yntax (mytuny)

This PR was merged into the 6.2 branch.

Discussion
----------

[ExpressionLanguage] Add support for null coalescing syntax

| Q             | A
| ------------- | ---
| Branch?       | 6.1
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Fix #45411, #21691
| License       | MIT
| Doc PR        | symfony/symfony-docs#16743

This is another waited feature for the syntax of the expression-language component. The [null-coalescing](https://wiki.php.net/rfc/isset_ternary) operator ``??`` becomes a need for variant programming needs these days.

Following my previous PR introducing the null-safe operator (#45795). I'm hereby introducing yet another essential operator to make the syntax even more complete.

The null-coalescing operator is a syntactic sugar for a common use of ternary in conjunction with ``isset()`` (in PHP) or equivalent in other languages. This is such a common use-case to the point that almost all majors programming syntax nowadays support a sort of a short-hand for that operation namely coalescing operator. Now it's time for the syntax of Expression-Language to do so!

Expressions like:

* ``foo.bar ?? 'default'``
* ``foo[3] ?? 'default'``
* ``foo.bar ?? foo['bar'] ?? 'default'``

will default to the expression in the right-hand-side of the ``??`` operator whenever the expression in the left-hand-side of it does not exist or it's ``null``. Note that this coalescing behavior can be chained and the validation logic takes decreasing priority from left to right.

Commits
-------

8e3c505 [ExpressionLanguage] Add support for null coalescing syntax
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Jul 29, 2022
…ytuny)

This PR was merged into the 6.1 branch.

Discussion
----------

[ExpressionLanguage] Feature Null-coalescing operator

<!--

If your pull request fixes a BUG, use the oldest maintained branch that contains
the bug (see https://symfony.com/releases for the list of maintained branches).

If your pull request documents a NEW FEATURE, use the same Symfony branch where
the feature was introduced (and `6.x` for features of unreleased versions).

-->

[ExpressionLanguage] [NEW FEATURE]

This PR introduces the support for null-coalescing operator ``??``.

The proposed change, includes a paragraph under the sub-page /expression_language/syntax to describe the new feature usage. The sub-paragraph has a title of **Null-coalescing operator** under the paragraph **Supported Operators**.

The actual work related to this Doc PR available as Symfony PR <!--symfony/symfony#45795>.

Commits
-------

81204c3 [ExpressionLanguage] Feature Null-coalescing operator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expression Language package: doesn't handle the absence of the property and an error displays
5 participants