-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Expression language]Trying to evaluate expression with a not existing variable in the array #21691
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
Comments
I'm hitting this issue as well but from another angle with upgrading an old Symfony 3.4 to 4.3. There is a deprecation notice regarding
should be converted into this:
However this won't work, because the Is there any progress on this issue or maybe a workaround that I am missing somehow? //cc @nicolas-grekas |
@steve-todorov Coincidentally - I've just encountered this same problem whilst trying to resolve deprecations. I think I might have figured a workaround tho' :) Old: * @Route("/add")
* @Route("/edit/{id}")
* @ParamConverter("client", options={"repository_method"="findApproved"}) New: * @Route("/add", defaults={"id"=null})
* @Route("/edit/{id}")
* @Entity("client", expr="repository.findApproved(id)") The defaults option means that there is an "id" declared even on the /add route, avoiding the explosion. This does mean that the repository method is getting passed a null, and needs to be able to handle that, but it seemed to already handle that in my case. |
Ha! I haven't thought of that! Thanks for sharing this workaround - works just fine! :) |
We encountered the same issue when trying to use ExpressionLanguage in our project. I would just like to point out few things/ideas
|
In Contao CMS Version 4.10 ExpressionLanguage is now used also for evaluating some input fields. Here one will have the same issue as described by tolecar:
I thus support the opinion that a non existing value should evaluate to null instead of throwing an exception. |
We solved the issue by extending Few days ago I published it on the github & packagist as separate library so you can try to use it. You can check it up on https://github.com/zef-dev/zef-expression-language and https://packagist.org/packages/zef-dev/zef-expression-language |
what you want is actually checking that what you could do is add a default of |
Thank you for this issue. |
I’m not aware that it’s been resolved.
|
It's definitely not resolved, I just stumbled on it too while using the Expression Language in a custom project. |
Yes, our workaround has been to completely side step use of Expression Language if/when a given key in the expression isn't "guaranteed" in the data available/provided for evaluation. From the consumer-side of this package, I do think evaluating non-existent identifiers to NULL might be a better design choice than throwing an exception or, at least, better as EL behavior controlled through a configurable option. |
My only workaround to this issue is to specifically catch the exception message and try again, which is really dirty code but at least allows you to use the expression language on arrays that may have missing keys. I hope this helps someone: tryagain:
try {
if ($expressionLanguage->evaluate($expression, $data)) {
// Success
}
}
catch (\Symfony\Component\ExpressionLanguage\SyntaxError $e) {
// Match the error message and variable name
if (preg_match('/^Variable "(?<var>[^"]+)" is not valid around position [0-9]+ for expression/', $e->getMessage(), $matched)) {
// Check that it is not in the data array (likely the cause)
if (!array_key_exists($matched['var'], $data)) {
$data[$matched['var']] = null;
goto tryagain;
} else {
throw $e;
}
} else {
throw $e;
}
} |
@prof83 That your workaround is coded using GOTO (lots of passion around this one on both sides) and regular expression pattern matching on the exception message itself just makes this all the more interesting, I think. It could probably be refactored as a DO-WHILE as a peace offering. I think this Symfony Expression Language behavior is the subject other other issues that have been opened (e.g. #41306), although referencing different Symfony versions (2.8 versus 5.2.7). |
I think we should keep the generated code as simple as possible. Thus not do anything to prevent the notice in the generated code. BUT I would suggest adding support for the nullsafe operator and the null coalescing! Anyone up for giving it a try? |
…r (mytuny) This PR was merged into the 6.1 branch. Discussion ---------- [ExpressionLanguage] Add support for null-safe operator | 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](https://wiki.php.net/rfc/nullsafe_operator) has been repeatedly reported as a BUG several time (e.g [#45411](#45411) & [#21691](#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](https://wiki.php.net/rfc/isset_ternary) operator. Another feature that I'm currently working on as well 💯 Commits ------- 946c59f [ExpressionLanguage] Add support for null-safe operator
…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
I'm trying to evaluate an expression with an array not containing all variables of the expression.
When i evaluate the expression with my array, the evaluation return a exception :
My problem is when i have a expression like
( ( var1 != 2 ) or ( var2 != 2 ) )
,and an array
this evaluation throw an exception. Should we not return a boolean instead of an exception ?
For exemple if we have the expression :
(a and b and c) or (d and e and f)
and e does not exist in the array, the expression (d and e and f) return false and not an exception.
The text was updated successfully, but these errors were encountered: