我有一个这样的嵌入式表单:
- >家长(班级)
| --->属性1(集合):children(class):必需
....... | ----->属性1:child_name(字符串):必需
....... | ----->属性2:child_description(字符串):必需
我希望,当我发送表格时:
如果收到的数据是这样的:
parent[children][__name__][child_name]=value1&parent[children][__name__][child_description]=value2
其中 name 是属性children
的ArrayCollection中的迭代因此,当我们在表单中发送两个孩子时,我们会得到以下数据:
parent[children][0][child_name]=value1&parent[children][0][child_description]=value2&parent[children][1][child_name]=value3&parent[children][1][child_description]=value4
我想要那个:
如果用户只发送任何内容(空表单),则会收到一个错误,即需要属性子项。
如果用户只发送child_name(或child_description)值,则会收到child_description(或child_name)也需要的错误。我的意思是如果他没有事件以这样的形式发送变量child_name(或child_description):
parent[children][__name__][child_name]=value1 (without the name and the value of the variable parent[children][__name__][child_description])
我尝试从实体验证此表单但是我遇到了一些问题。
在父实体类中:
/**
* Parent
*
* @ORM\Table(name="parent")
* @ORM\Entity
*/
class Parent
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var \Doctrine\Common\Collections\ArrayCollection
*
* @Assert\NotBlank(message="Error", groups={"Creation"})
* @Assert\NotNull(message="Error", groups={"Creation"}))
* @Assert\Count(
* min = 1,
* minMessage = "Error",
* groups={"Creation"}
* )
* @ORM\OneToMany(targetEntity="Children", mappedBy="parent", cascade={"ALL"}, orphanRemoval=true)
*/
protected $children;
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Add child
*
* @param Child $child
* @return children
*/
public function addChild(Child $child)
{
$this->children[] = $child;
$child->setParent($this);
return $this;
}
/**
* Remove child
*
* @param Child $child
*/
public function removeChild(Child $child)
{
$this->children->removeElement($child);
}
public function getChildren()
{
return $this->children;
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
}
然后,Child Entity类:
/**
* Child
*
* @ORM\Table(name="child")
* @UniqueEntity(
* fields={"child_name","child_description"},
* message="already registred"
* )
*/
class Child
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var Parent
*/
private $parent;
/**
* @ORM\Column(name="child_name", type="string", length=255 )
*
* Assert\NotBlank(message="empty", groups={"Creation"})
* Assert\NotNull(message="null", groups={"Creation"})
* @Assert\Length(
* min=3,
* minMessage="too short",
* groups={"Creation"}
* )
* @Assert\Type(
* type="string",
* message="you need a string",
* groups={"Creation"}
* )
*/
private $child_name;
/**
* @ORM\Column(name="child_description", type="string", length=255 )
*
* Assert\NotBlank(message="empty", groups={"Creation"})
* Assert\NotNull(message="null", groups={"Creation"})
* @Assert\Length(
* min=3,
* minMessage="too short",
* groups={"Creation"}
* )
* @Assert\Type(
* type="string",
* message="you need a string",
* groups={"Creation"}
* )
*/
private $child_description;
public function __construct()
{}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set childName
*
* @param string $childName
*
* @return Child
*/
public function setChildName($childName)
{
$this->child_name = $childName;
return $this;
}
/**
* Get childName
*
* @return string
*/
public function getChildName()
{
return $this->child_name;
}
/**
* Set childDescription
*
* @param string $childDescription
*
* @return Child
*/
public function setChildDescription($childDescription)
{
$this->child_description = $childDescription;
return $this;
}
/**
* Get childDescription
*
* @return string
*/
public function getDescription()
{
return $this->child_description ;
}
在Controller类中:
public function postChildrenAction(Request $request)
{
$result = new Parent();
$em = $this->get('doctrine.orm.entity_manager');
$form = $this->createForm(ParentType::class, $result, array(
'validation_groups' => array('Creation', 'Default'),
));
$form->submit($request->request->get($form->getName()));
if ($form->isSubmitted() && $form->isValid()) {
//persistance
}
}
在ParentType类中:
class ParentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('children', CollectionType::class,array(
'entry_type' => ChildType::class,
'required'=> true,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'constraints' => array(new Valid()), // __LINE_A__
'entry_options' => array(
'validation_groups' => $options['validation_groups'],
'required'=> true,
),
));
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Path\NameBundle\Entity\Parent',
'csrf_protection' => false,
'validation_groups' => array('Creation', 'Default'),
'cascade_validation' => true,
'error_bubbling' => false,
]);
}
}
最后是ChildType:
class ChildType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('child_name',TextType::class,array('required'=> true,'validation_groups'=>$options['validation_groups']));
$builder->add('child_description',TextType::class,array('required'=> true,'validation_groups'=>$options['validation_groups']));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Path\NameBundle\Entity\Child',
'csrf_protection' => false,
'validation_groups' => array('Creation', 'Default'),
'cascade_validation' => true,
'error_bubbling' => false,
]);
}
}
第一个问题出现在Parent Entity类中:当我从children属性中删除Assert \ Count()约束时,验证将成功。那么为什么约束NotBlank和NotNull不起作用?
如果我在ParentType中注释行'constraints' => array(new Valid())
(__LINE_A__
),则ChildType的约束UniqueEntity将不起作用。为什么?
ParentType和ChildType中的'required' => true
个选项均无效。当我只发送没有描述的子名称(或反向)时,我得到一个SQL错误,说明描述的值为空。
当表单为空时,验证将成功,但我需要在缺少某些数据时(对于子对象或父对象)收到错误。
即使我启用'cascade_validation' => true
,如果表单与缺少的变量一起发送,则父/子实体类中的groups选项也不起作用。
这太难了。
要完成这篇文章,我想知道: