[Form] String is the preferred value type for TextType #41514
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I want to return to an old and very painful topic #5906. I wanted to revisit this topic before the release 4.0 and 5.0, but didn't find the time for this. Now, when everyone already has PHP 7 or 8, and the
strict_types=1is the defect standard, it is probably time to abandon the hook when the text may not be astring.We've been using hooks for many years, even before #18357. We want string values to always be strings. Under strict typing conditions, i consider using
NULLas a value valid only in cases where the expected value is not a scalar type and cannot be correctly transformed from the submitted data. In such cases, we use custom transformers.Expected implementation
A very crude example.
Actual implementation
Without hooks and specifying option
empty_data.use Symfony\Component\Validator\Constraints as Assert; final class RenameAuthor { /** * @Assert\NotBlank * @Assert\Length(max=128) */ - public string $firstname = ''; + private string $firstname = ''; /** * @Assert\Length(max=128) */ - public string $lastname = ''; + private string $lastname = ''; /** * @Assert\Length(max=128) */ - public string $patronymic = ''; + private string $patronymic = ''; + + public function getFirstname(): string + { + return $this->firstname; + } + + public function setFirstname(?string $firstname): void + { + $this->firstname = $firstname ?? ''; + } + + public function getLastname(): string + { + return $this->lastname; + } + + public function setLastname(?string $lastname): void + { + $this->lastname = $lastname ?? ''; + } + + public function getPatronymic(): string + { + return $this->patronymic; + } + + public function setPatronymic(?string $patronymic): void + { + $this->patronymic = $patronymic ?? ''; + } }$command = new RenameAuthor(); $form = $this->createForm(RenameAuthorFormType::class, $command)->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $questionnaire->renameAuthor($command->firstname, $command->lastname, $command->patronymic); + $questionnaire->renameAuthor($command->getFirstname(), $command->getLastname(), $command->getPatronymic()); // ... }Implementation with empty_data option
It seems that specifying one option is not a problem. But you should always remember that the text may not be a
string, and to typecast to astring, you need to specify optionempty_datain each field, each form. There may be hundreds and thousands of such places per project, and the probability of errors increases with the growth of the project.use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; final class RenameAuthorFormType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder - ->add('firstname', TextType::class) + ->add('firstname', TextType::class, [ + 'empty_data' => '', + ]) ->add('lastname', TextType::class, [ + 'empty_data' => '', 'required' => false, ]) ->add('patronymic', TextType::class, [ + 'empty_data' => '', 'required' => false, ]) ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefault('data_class', RenameAuthor::class); } }