Symfony非映射必填字段前后端校验不一致问题
isValid() Not Validating Non-Mapped Required Checkbox Ah, I’ve run into this exact quirk before! The issue here is that setting required: true on a non-mapped field (mapped: false) only adds the HTML required attribute for frontend browser validation—it doesn’t trigger Symfony’s backend form validator to actually check the field.
To get $form->isValid() to properly validate that the checkbox is checked, you need to explicitly add a validation constraint to the field. Here’s how to fix it:
Step 1: Import the Appropriate Constraint
First, add the IsTrue constraint (ideal for "must be checked" checkbox scenarios) at the top of your form class:
use Symfony\Component\Validator\Constraints\IsTrue;
Step 2: Attach the Constraint to Your Field
Update your field definition to include the constraints option, which tells Symfony’s validator to enforce the check:
$builder->add('termsAndConditions', CheckboxType::class, [ 'required' => true, 'mapped' => false, 'attr' => [ 'class' => 'c-custom-option', ], 'constraints' => [ new IsTrue([ 'message' => 'You must agree to the terms and conditions to continue.', ]), ], ]);
Why This Works
- The
required: trueflag only handles frontend validation. For backend validation (whichisValid()depends on), non-mapped fields don’t get default validation rules—you have to define them explicitly. - The
IsTrueconstraint ensures the checkbox’s value is strictlytrue, which is exactly what you need for a "terms of service" checkbox. While you could useNotBlank,IsTrueis more semantically correct here, since unchecked checkboxes typically submitfalseornull.
With this change, calling $form->isValid() will automatically validate that the termsAndConditions checkbox is checked, and you can remove that extra manual check from your controller code.
内容的提问来源于stack exchange,提问作者Quisse

