-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Form] Deprecated usage of "choices" option in sub types #21919
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,13 +14,15 @@ | |
use PHPUnit\Framework\TestCase; | ||
use Symfony\Component\Form\Forms; | ||
use Symfony\Component\Form\Tests\Fixtures\ChoiceTypeExtension; | ||
use Symfony\Component\Form\Tests\Fixtures\LazyChoiceTypeExtension; | ||
|
||
class ExtendedChoiceTypeTest extends TestCase | ||
{ | ||
/** | ||
* @group legacy | ||
* @dataProvider provideTestedTypes | ||
*/ | ||
public function testChoicesAreOverridden($type) | ||
public function testLegacyChoicesAreOverridden($type) | ||
{ | ||
$factory = Forms::createFormFactoryBuilder() | ||
->addTypeExtension(new ChoiceTypeExtension($type)) | ||
|
@@ -36,6 +38,44 @@ public function testChoicesAreOverridden($type) | |
$this->assertSame('b', $choices[1]->value); | ||
} | ||
|
||
/** | ||
* @dataProvider provideTestedTypes | ||
*/ | ||
public function testChoicesAreOverridden($type) | ||
{ | ||
$factory = Forms::createFormFactoryBuilder() | ||
->addTypeExtension(new ChoiceTypeExtension($type)) | ||
->getFormFactory() | ||
; | ||
|
||
$choices = $factory->create($type, null, array('choice_loader' => null))->createView()->vars['choices']; | ||
|
||
$this->assertCount(2, $choices); | ||
$this->assertSame('A', $choices[0]->label); | ||
$this->assertSame('a', $choices[0]->value); | ||
$this->assertSame('B', $choices[1]->label); | ||
$this->assertSame('b', $choices[1]->value); | ||
} | ||
|
||
/** | ||
* @dataProvider provideTestedTypes | ||
*/ | ||
public function testChoiceLoaderIsOverridden($type) | ||
{ | ||
$factory = Forms::createFormFactoryBuilder() | ||
->addTypeExtension(new LazyChoiceTypeExtension($type)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need the type extension here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would keep it like it for consistency with the test above, and because it test both overriding the option directly and doing it with an extension, so looks safer as is. |
||
->getFormFactory() | ||
; | ||
|
||
$choices = $factory->create($type)->createView()->vars['choices']; | ||
|
||
$this->assertCount(2, $choices); | ||
$this->assertSame('Lazy A', $choices[0]->label); | ||
$this->assertSame('lazy_a', $choices[0]->value); | ||
$this->assertSame('Lazy B', $choices[1]->label); | ||
$this->assertSame('lazy_b', $choices[1]->value); | ||
} | ||
|
||
public function provideTestedTypes() | ||
{ | ||
yield array(CountryTypeTest::TESTED_TYPE); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Form\Tests\Fixtures; | ||
|
||
use Symfony\Component\Form\AbstractTypeExtension; | ||
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; | ||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | ||
use Symfony\Component\OptionsResolver\OptionsResolver; | ||
|
||
class LazyChoiceTypeExtension extends AbstractTypeExtension | ||
{ | ||
private $extendedType; | ||
|
||
public function __construct($extendedType = ChoiceType::class) | ||
{ | ||
$this->extendedType = $extendedType; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function configureOptions(OptionsResolver $resolver) | ||
{ | ||
$resolver->setDefault('choice_loader', new CallbackChoiceLoader(function () { | ||
return array( | ||
'Lazy A' => 'lazy_a', | ||
'Lazy B' => 'lazy_b', | ||
); | ||
})); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getExtendedType() | ||
{ | ||
return $this->extendedType; | ||
} | ||
} |
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.
That doesn't look intuitive to me.
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, this is because choice_loader has priority over choices in ChoiceType (which is not documented IIRC btw)
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.
And this should not be used ideally, the ChoiceType is more accurate in such cases, I'll update the doc to clarify this.
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.
Wouldn't it be "better" to drop this example and just keep the second code snippet? And remove the recommendation to use
choice_loader
as null?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.
I understand this does not look pretty, but this is the actual quick fix for some breaking app.
What we can't do is to stop supporting "choices" option as it's inherited from the ChoiceType, and in such cases
null
is needed because of its precedence.What we can do is to better document these types options, and explicit that "choices" or "choice_loader" options should be overridden on a ChoiceType or an EntityType only, not on a child already doing so, unless the previous value is reused.
I would like to address your comment, but as I said in a previous outdated diff:
Then the real fix would be to use the ChoiceType (if the previous "choices" values is not used), I could add this instead, but objectively I would let it as is now.
I'm waiting for your final call on this symfony deciders.
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.
I am fine with how it is now. But we should indeed clarify the documentation about the differences of the
choices
andchoice_loader
options and when to use what.