我创建了一个实体Testme
,并使用bin/console make:crud
生成了crud文件,并尝试向该表单添加验证规则,但是它不起作用:
我的实体:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\TestmeRepository")
*/
class Testme
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @Assert\NotBlank()
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $description;
....
表格:
<?php
namespace App\Form;
use App\Entity\Testme;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TestmeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Testme::class,
]);
}
}
控制器动作:
/**
* @Route("/{id}/edit", name="testme_edit", methods="GET|POST")
*/
public function edit(Request $request, Testme $testme): Response
{
$form = $this->createForm(TestmeType::class, $testme);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('testme_edit', ['id' => $testme->getId()]);
}
return $this->render('testme/edit.html.twig', [
'testme' => $testme,
'form' => $form->createView(),
]);
}
如果name
字段为空,则在创建新实体时会正确显示验证错误,但是当我编辑它并清空name
字段时,我得到一个InvalidArgumentException
$form->handleRequest($request);
行:
期望的类型为“字符串”,“ NULL”的参数。
我想念什么?
编辑:所有代码都是由make:Entity
和make:crud
命令生成的,我只在@Assert\NotBlank()
属性上添加了$name
。
答案 0 :(得分:4)
在任何验证之前 应用表格和发布的数据绑定。如果您提示设置器/加法器,则将在这种情况下运行。
在我的POV中,您不应为了满足第三方代码(此处为表单组件)而修改“模型”代码,因为这样可能会遇到诸如错误使用方法的问题(如果需要输入值,确保“非空”要求的唯一可能方法是避免接受空;一旦“忘记”在对象上调用valid
,验证器本身将不执行任何操作,即使在这种情况下,您仍然拥有有效的和可刷新对象。
相反,您应该将DTO或ValueObjects绑定到表单。这些对象可以接受您想要的任何类型的值(基本上是您期望的值,并且为null)。然后,您可以执行验证,例如,使用“命令”(不是DDD“概念”中的symfony,而是“命令”)可以填充并执行其他“数据传递”或对 real < / em>实体。
即使ste的答案将使其起作用,从概念上讲也是错误的,因为将您的代码暴露于此答案中上面解释的“域风险”。
答案 1 :(得分:1)
您应删除实体设置器中的类型提示,或将参数默认设置为null。
如果未更改字段(例如,在使用新对象的情况下),则表单组件可能不会更新字段(即调用setXXX)。
验证是在对象中完成的,因为在那里定义了约束(即@Assert批注)。
您可以使用约束直接在表单中进行验证。参见https://symfony.com/doc/current/form/without_class.html#adding-validation