Symfony3 - 嵌入表单的验证

时间:2018-01-08 01:22:27

标签: forms symfony validation constraints

我有一个这样的嵌入式表单:

- >家长(班级)

| --->属性1(集合):children(class):必需

....... | ----->属性1:child_name(字符串):必需

....... | ----->属性2:child_description(字符串):必需

我希望,当我发送表格时:

  1. 至少发送了一个父对象(我的意思是children属性至少包含一行(child_name和child_description)
  2. 如果收到的数据是这样的:

    • 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

    我想要那个:

    1. 如果用户只发送任何内容(空表单),则会收到一个错误,即需要属性子项。

    2. 如果用户只发送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])
    3. 我尝试从实体验证此表单但是我遇到了一些问题。

      在父实体类中:

      /**
       * 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,
              ]);
          }
      }
      
      1. 第一个问题出现在Parent Entity类中:当我从children属性中删除Assert \ Count()约束时,验证将成功。那么为什么约束NotBlank和NotNull不起作用?

      2. 如果我在ParentType中注释行'constraints' => array(new Valid())__LINE_A__),则ChildType的约束UniqueEntity将不起作用。为什么?

      3. ParentType和ChildType中的'required' => true个选项均无效。当我只发送没有描述的子名称(或反向)时,我得到一个SQL错误,说明描述的值为空。

      4. 当表单为空时,验证将成功,但我需要在缺少某些数据时(对于子对象或父对象)收到错误。

      5. 即使我启用'cascade_validation' => true,如果表单与缺少的变量一起发送,则父/子实体类中的groups选项也不起作用。

      6. 这太难了。

        要完成这篇文章,我想知道:

        1. 我们在实体类中定义的约束不是验证表单的约束吗?因为当我在validation.yml中创建相同的约束时(使用带有child_name和child_description的NotBlank),验证工作正常,如果缺少变量/数据则失败。
        2. 感谢您回答我其中一个问题。

0 个答案:

没有答案