Symfony2.8项目 通过注释NOT YML进行子表单验证 没有实体或学说参与
主窗体通过注释确认。收集字段,子表单无法验证。无论您输入什么内容,当主表单字段有效时,子表单中的每个字段都将作为有效字段传递。
我在网上尝试了很多建议,
' error_bubbling',' cascade_validation'以及@Valid()标记。什么都行不通。
我已将var_dump(...)添加到symfony2代码库中的RangeValidator类,并且未创建/调用它。为了证明它没有被使用,我将一个子表单字段复制到主表单,然后调用框架的验证程序进行范围检查,它应该对子表单中的某些字段执行,而不是。
显然有更多的代码,包括客户端javascript,但下面是一个基本的代码片段(从我的代码中挖出了这个问题):
Main form:
class SubsetAdd extends AbstractType
{
/**
* @var string
*
* @Assert\NotBlank(
* message="Subset name should not be blank"
* )
* @Assert\Regex(
* pattern="/^[\w\s\d\:\_\-\+]{1,64}$/",
* message="Subset name should contain ..."
* )
*/
protected $subsetName;
/**
* @var string
*
* @Assert\Regex(
* pattern="/^[\d]{1,4}[Kk]{1}$/",
* message="Baud rate should be <n>K"
* )
*/
protected $baud;
/**
* @Assert\Valid()
*/
protected $entries;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setMethod('POST');
$builder->add('subsetName',
Type\TextType::class,
array(
'attr' => array(
'title' => 'Subset name string',
),
'required' => true,
'label' => 'Subset'
)
);
$builder->add('baud', Type\ChoiceType::class, array(
'label' => 'Baud',
'attr' => array(
'title' => 'Baud rate',
),
'placeholder' => 'Select Baud',
'required' => true,
'choices' => array('9600'=>'9600','115200'=>'115200'),
));
$builder->add('entries', Type\CollectionType::class, array(
'label' => 'Entries',
'type' => Module\EntryType::class,
'allow_add' => true,
'allow_delete' => true,
'required' => true,
'prototype' => true,
'prototype_name' => 'entries__name__',
));
if ($options['submit']) {
// manual debugging aid. normally client side ajax does the submit so no button required
$builder->add('submit',Type\SubmitType::class);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array(
'submit',
));
$resolver->setDefaults(array(
'submit'=>false,
'translation_domain' => 'SerialBundle-forms',
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => __CLASS__, // this class is the data object the form represents
);
return $options;
}
public function getName()
{
$cn=substr(__CLASS__,(strlen(__NAMESPACE__)>0?1+strlen(__NAMESPACE__):0)); // class name - namespace
return strtolower(substr($cn,0,1)).substr($cn,1); // lower case first letter
}
public function getBlockPrefix() {
return $this->getName();
}
public function setSubsetName($name)
{
$this->subsetName = $name;
return $this;
}
public function getSubsetName()
{
return $this->subsetName;
}
public function setBaud($baud)
{
$this->baud = $baud;
return $this;
}
public function getBaud()
{
return $this->baud;
}
public function setEntries($entries) {
$this->entries=$entries;
}
public function getEntries() {
return $this->entries;
}
}
Subform:
class EntryType extends AbstractType
{
/**
* @var string
*
* @Assert\Regex(
* pattern="/^[\dA-F]+$/",
* message="Ident should be hex value"
* )
* @Assert\Valid()
*/
protected $ident;
/**
* @var integer
*
* @Assert\Range(
* min = 0,
* max = 64,
* minMessage="Start minimum value?",
* maxMessage="Start maximum value?"
* )
* @Assert\Valid()
*/
protected $start;
/**
* @var integer
*
* @Assert\Range(
* min = 0,
* max = 64,
* minMessage="Length minimum value?",
* maxMessage="Lenght maximum value?"
* )
* @Assert\Valid()
*/
protected $length;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setMethod('POST');
$builder->add('ident',
Type\TextType::class,
array(
'attr' => array(
'title' => 'Ident value',
),
'required' => true,
'label' => 'Ident'
)
);
$builder->add('start',
Type\TextType::class,
array(
'attr' => array(
'title' => 'Start value',
),
'required' => true,
'label' => 'Start'
)
);
$builder->add('length',
Type\TextType::class,
array(
'attr' => array(
'title' => 'Length value',
),
'required' => true,
'label' => 'Length'
)
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array(
));
$resolver->setDefaults(array(
'translation_domain' => 'SerialBundle-forms',
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => __CLASS__, // this class is the data object the form represents
);
return $options;
}
public function getName()
{
$cn=substr(__CLASS__,(strlen(__NAMESPACE__)>0?1+strlen(__NAMESPACE__):0)); // class name - namespace
return strtolower(substr($cn,0,1)).substr($cn,1); // lower case first letter
}
public function getBlockPrefix() {
return $this->getName();
}
public function setIdent($id)
{
$this->ident = $id;
return $this;
}
public function getIdent()
{
return $this->ident;
}
public function setStart($start)
{
$this->start = $start;
return $this;
}
public function getStart()
{
return $this->start;
}
public function setLength($length)
{
$this->length = $length;
return $this;
}
public function getLength()
{
return $this->length;
}
}
Basic controller:
class SubsetsController extends Controller
{
...
/**
* @Route("/add", name="subsets-add")
* @Method({"GET","POST"})
*/
public function addFormAction(Request $request)
{
$subsetAdd=new ModuleForm\SubsetAdd();
$options=array(
'submit'=>false,
);
$form = $this->createForm(ModuleForm\SubsetAdd::class, $subsetAdd, $options);
$form->handleRequest($request);
if ($form->isSubmitted()) {
var_dump('Submitted');
if ($form->isValid()) {
var_dump('Valid');
var_dump("<pre>");
var_dump($subsetAdd->getEntries());
var_dump("</pre>");
}
}
return $this->render("SerialBundle:Subsets/form.subsets.html.twig', array(
'anyerrors' => (($form->isSubmitted() && !$form->isValid())?true:false),
'form' => $form->createView(), // invoked after handlerequest
));
}
}
答案 0 :(得分:1)
如何使用'constraints'=&gt;新的有效()?
$builder->add('entries', Type\CollectionType::class, array(
'constraints' => new Valid(),
'label' => 'Entries',
'type' => Module\EntryType::class,
'allow_add' => true,
'allow_delete' => true,
'required' => true,
'prototype' => true,
'prototype_name' => 'entries__name__',
));