Symfony4 API使用Nelmio Api Doc时POST布尔值始终返回true问题
mandatory_registration始终返回true的问题 看起来你遇到的问题是提交mandatoryRegistration=false时,后端总是把该字段设为true,这大概率和表单字段的类型处理、Entity默认值或者Controller逻辑有关,我帮你一步步排查:
1. 检查表单类型(Form Type)的字段定义
这是最常见的原因:如果你的表单中mandatoryRegistration用的是CheckboxType,那么它对x-www-form-urlencoded格式的布尔值处理逻辑和你预期的不一样。
CheckboxType的规则是:只有当请求中存在该字段(不管值是什么),都会被解析为true;如果字段不存在,才会设为false。所以你提交的mandatoryRegistration=false会被视为“字段存在”,直接转成true。
解决方案:改用BooleanType
把表单字段类型换成BooleanType,它可以正确解析字符串形式的"true"/"false"为对应布尔值:
// src/Form/EventTypeFormType.php use Symfony\Component\Form\Extension\Core\Type\BooleanType; // ... $builder ->add('fullName', TextType::class) ->add('shortName', TextType::class) ->add('dns', TextType::class) ->add('mandatoryRegistration', BooleanType::class, [ 'required' => false, // 允许不提交该字段 ]);
2. 检查Entity字段的默认值
看看你的EventType实体中,mandatoryRegistration字段是不是默认设置为true了:
// src/Entity/EventType.php use Doctrine\ORM\Mapping as ORM; /** * @ORM\Column(type="boolean", name="mandatory_registration", options={"default": true}) */ private $mandatoryRegistration = true;
如果表单没有正确处理提交的false值(比如字段类型不对导致解析失败),就会使用这个默认值,导致结果为true。
解决方案:调整默认值(如果需要)
如果业务上不需要默认true,就把默认值改成false,或者去掉options={"default": true}:
/** * @ORM\Column(type="boolean", name="mandatory_registration", options={"default": false}) */ private $mandatoryRegistration = false;
3. 检查Controller中的逻辑
确认你的Controller没有在表单提交后,手动强制把该字段设为true:
// src/Controller/EventTypeController.php public function createEventType(Request $request) { $eventType = new EventType(); $form = $this->createForm(EventTypeFormType::class, $eventType); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { // 检查这里有没有手动覆盖值! // $eventType->setMandatoryRegistration(true); // 这会直接覆盖提交的值 $em = $this->getDoctrine()->getManager(); $em->persist($eventType); $em->flush(); return $this->json($eventType); } return $this->json($form->getErrors(true), Response::HTTP_BAD_REQUEST); }
4. 验证请求数据是否被正确接收
可以在Controller中临时添加调试代码,确认请求中的值是否被正确读取:
// 在handleRequest之前添加 var_dump($request->request->get('mandatoryRegistration')); // 应该输出字符串"false" die;
如果输出的是"false",那问题就出在表单的类型转换上;如果输出的是null,说明请求参数名可能和表单字段名不匹配(比如你用了mandatoryRegistration但表单字段是mandatory_registration?不过看你的请求参数是mandatoryRegistration,应该对应实体的驼峰字段名)。
额外方案:添加数据转换器(如果坚持用CheckboxType)
如果你因为某些原因必须用CheckboxType,可以添加一个数据转换器来处理字符串的布尔值:
// src/Form/EventTypeFormType.php use Symfony\Component\Form\CallbackTransformer; // ... $builder->add('mandatoryRegistration', CheckboxType::class, [ 'required' => false, ]) ->get('mandatoryRegistration') ->addModelTransformer(new CallbackTransformer( // 从实体转表单(不需要修改) function ($value) { return $value; }, // 从表单转实体:把字符串转成布尔值 function ($value) { return $value === 'true' || $value === true; } ));
这样提交mandatoryRegistration=false时,就会被转换成布尔false。
内容的提问来源于stack exchange,提问作者France Benoit

