-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Form] Deprecate searchAndRenderBlock
returning empty string
#27247
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
[Form] Deprecate searchAndRenderBlock
returning empty string
#27247
Conversation
c214eb1
to
ad04302
Compare
That'd be for 4.2 now. |
This isn't new feature so shouldn't be affected by feature freeze. But understood. |
Semver defines that deprecations should follow the same process as features. |
Changed the base. Should I create UPGRADE-4.2.md in root now? |
yes please |
UPGRADE-4.1.md
Outdated
After: | ||
```twig | ||
{% for field in fields %} | ||
{% if not field.rendered %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is a bit misleading to me. Quickly reading it, you might think this check is always necessary when iterating form fields to render them.
I'd rather show an example where you need to render the same field twice and thus store the result in a variable which would be rendered twice in the "after" code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit misleading yes. But your suggested example is misleading too. Current code does not allow to render same field twice and neither this patch allows that. We shouldn't present a solution for rendering same field multiple times, as this has nothing to do with that.
Maybe example should just rename fields
into fieldsWithPossibleDuplicates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright
@@ -398,7 +398,7 @@ | |||
{# Support #} | |||
|
|||
{%- block form_rows -%} | |||
{% for child in form %} | |||
{% for child in form if not child.rendered %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we really do this change? Better get the deprecation and then the exception if you're trying to render the same row twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this required to support partial form auto-rendering?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already supposed to be handled in form_rest
:
symfony/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
Lines 376 to 381 in 4a7e6fa
{%- block form_rest -%} | |
{% for child in form -%} | |
{% if not child.rendered %} | |
{{- form_row(child) -}} | |
{% endif %} | |
{%- endfor -%} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is necessary for tests to pass, which means not doing this would be BC break
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which test? If the test is failing by triggering the deprecation, that's expected and should by marked as legacy, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok yes, it's just deprecation. It was triggered by FormExtensionDivLayoutTest, inherited testcase testRestWithChildrenForms.
Negative of just marking tests as legacy is that it triggers unresolvable deprecation notices in user land. There should be some effort in avoiding it, not just mark test as legacy as first thing IMHO.
I might have found another way though
edit: here is a chain of calls which trigger deprecation:
form_rest -> form_row -> form_widget_compound -> form_rows
ad04302
to
259ef8b
Compare
@@ -132,6 +132,9 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va | |||
$renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix; | |||
|
|||
if ($renderOnlyOnce && $view->isRendered()) { | |||
// This is not allowed, because it would result in rendering same IDs multiple times, which is not valid. | |||
@trigger_error(sprintf('Calling the "%s()" method for fields which were already rendered is deprecated since Symfony 4.1 and will throw an exception in 5.0.', __METHOD__), E_USER_DEPRECATED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be 4.2 here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add the field name here as well to help figuring out where that comes from in an app?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
people don't call searchAndRenderBlock
directly, so this deprecation is confusing as they probably don't know about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stof What do you suggest? I agree people don't call this directly, but formRenderer is responsible for this confusing behavior so deprecation needs to be triggered from within.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, $blockNameSuffix
allows you to know whether form_row
or form_widget
was called originally, so you can use it to report it.
and I agree about the field name
UPGRADE-4.2.md
Outdated
---- | ||
|
||
* Deprecated calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered. | ||
Instead of expecting such calls return empty string, check if field has already been rendered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole block must be indented properly under the *
to fix rendering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...] calls to return [...] if the field [...]
4.2.0 | ||
----- | ||
|
||
* deprecated calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the dot should be removed
@@ -22,7 +22,6 @@ | |||
{%- if form is rootform -%} | |||
{{ form_errors(form) }} | |||
{%- endif -%} | |||
{{- block('form_rows') -}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a BC break in case someone overwrites the block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this reason I liked #27247 (diff) solution more. That would be BC break too in case someone overrides FormRenderer (and expect it to be called for already rendered field too), but that is much less likely imho. What do you think?
@@ -2,6 +2,5 @@ | |||
<?php if (!$form->parent && $errors): ?> | |||
<?php echo $view['form']->errors($form) ?> | |||
<?php endif ?> | |||
<?php echo $view['form']->block($form, 'form_rows') ?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same issue here about the BC break
@@ -132,6 +132,9 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va | |||
$renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix; | |||
|
|||
if ($renderOnlyOnce && $view->isRendered()) { | |||
// This is not allowed, because it would result in rendering same IDs multiple times, which is not valid. | |||
@trigger_error(sprintf('Calling the "%s()" method for fields which were already rendered is deprecated since Symfony 4.1 and will throw an exception in 5.0.', __METHOD__), E_USER_DEPRECATED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
people don't call searchAndRenderBlock
directly, so this deprecation is confusing as they probably don't know about it.
70840ed
to
3e54c12
Compare
status: needs review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor CS
UPGRADE-4.2.md
Outdated
{{ form_widget(field) }} | ||
{% endif %} | ||
{% endfor %} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing empty line after the end of this block
@@ -132,6 +132,9 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va | |||
$renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix; | |||
|
|||
if ($renderOnlyOnce && $view->isRendered()) { | |||
// This is not allowed, because it would result in rendering same IDs multiple times, which is not valid. | |||
@trigger_error(sprintf('You are calling "form_%s" for field "%s" which has already been rendered before. Trying to render fields which were already rendered is deprecated since Symfony 4.2 and will throw an exception in 5.0.', $blockNameSuffix, $view->vars['name']), E_USER_DEPRECATED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're trying to have only one sentence for deprecations. Might be changed to [...] rendered before, try [...]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This?
You are calling "form_%s" for field "%s" which has already been rendered before, trying to render fields which were already rendered is deprecated since Symfony 4.2 and will throw an exception in 5.0.
I think there is too much information in there for one sentence. I don't know how to fit all of it in a way sentence seems natural 🤔
UPGRADE-4.2.md
Outdated
After: | ||
```twig | ||
{% for field in fieldsWithPotentialDuplicates %} | ||
{% if not field.rendered %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be simplified: {% for field in fieldsWithPotentialDuplicates if not field.rendered %}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC this kind of filtering has limitations, depending on what's inside the for block, so I went with safer approach here. But I don't remember what was the issue then, so will change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the limitation is that any loop.*
variables depending on the number of items in the loop won't work anymore (because it won't know in advance).
But if you skip the rendering entirely for some items with an inner filtering, these would not work well anyway, as some code using loop.last
would probably expect it to be the last rendered item, not the last checked one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So do you think we should still go with short way? Another limitation is when you don't want to skip whole loop cycle, but only rendering
{% for field in fieldsWithPotentialDuplicates %}
{# ...some code which works with field... #}
{% if not field.rendered %}
{{ form_row(field) }}
{% endif %}
{% endif %}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then it is not the same original code (and then, you would have to evaluate whether the additional code should run when the field does not get rendered), and so requires a case-by-case decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(after rebase)
041e9d2
to
5b47226
Compare
Rebased. Failures unrelated |
UPGRADE-4.2.md
Outdated
---- | ||
|
||
* Deprecated calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered. | ||
Instead of expecting such calls to return empty string, check if the field has already been rendered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strings
5b47226
to
c7e01f4
Compare
status: needs review |
c7e01f4
to
02f2f0e
Compare
Thank you @ostrolucky. |
…y string (ostrolucky) This PR was squashed before being merged into the 4.2-dev branch (closes #27247). Discussion ---------- [Form] Deprecate `searchAndRenderBlock` returning empty string | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | #26531 | License | MIT | Doc PR | - I would like to remove this silent behavior, because it's confusing Commits ------- 02f2f0e [Form] Deprecate `searchAndRenderBlock` returning empty string
…eady rendered (yceruto) This PR was merged into the 5.0-dev branch. Discussion ---------- [Form] Throw exception when render a field which was already rendered | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - See #27247 Commits ------- d1bbad0 Throw exception when render a field which was already rendered
I would like to remove this silent behavior, because it's confusing