2016-02-19 142 views
0

只有当来自CollectionType的输入存在于窗体上时,我如何验证AdMenuLinkType形式的CollectionType。Symfony2 CollectionType验证

例如:当我在浏览器中打开添加表单时,我可以创建没有路由参数的链接。当我点击按钮“添加参数” - JavaScript从AdMenuRouteDataType窗体呈现2个字段。这两个字段必须是必需的而不是空的。如果我使用这些空白字段提交表单 - 我需要获取错误。如果我不点击“添加参数”按钮,集合输入字段不呈现,我可以提交表单没有这些数据和错误。我如何做到这一点?

我有实体:AdMenuRouteData

<?php 

namespace AdBackendBundle\Entity; 

use Doctrine\Common\Collections\ArrayCollection; 
use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Validator\Constraints as Assert; 

/** 
* AdMenuRouteData 
* 
* @ORM\Table(name="ad_menu_route_data") 
* @ORM\Entity(repositoryClass="AdBackendBundle\Repository\AdMenuRouteDataRepository") 
*/ 
class AdMenuRouteData 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="AdBackendBundle\Entity\AdMenuLink", inversedBy="routeData") 
    * @ORM\JoinColumn(name="link_id", referencedColumnName="id", onDelete="CASCADE") 
    */ 
    private $link; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="parameter", type="string", length=255) 
    * @Assert\NotBlank(message="ad_menu_route_data.parameter.blank") 
    */ 
    private $parameter; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="value", type="string", length=255) 
    * @Assert\NotBlank(message="ad_menu_route_data.value.blank") 
    */ 
    private $value; 

    /** 
    * Get id 
    * 
    * @return int 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * @return mixed 
    */ 
    public function getLink() 
    { 
     return $this->link; 
    } 

    /** 
    * @param mixed $link 
    */ 
    public function setLink($link) 
    { 
     $this->link = $link; 
    } 

    /** 
    * Set parameter 
    * 
    * @param string $parameter 
    * 
    * @return AdMenuRouteData 
    */ 
    public function setParameter($parameter) 
    { 
     $this->parameter = $parameter; 

     return $this; 
    } 

    /** 
    * Get parameter 
    * 
    * @return string 
    */ 
    public function getParameter() 
    { 
     return $this->parameter; 
    } 

    /** 
    * Set value 
    * 
    * @param string $value 
    * 
    * @return AdMenuRouteData 
    */ 
    public function setValue($value) 
    { 
     $this->value = $value; 

     return $this; 
    } 

    /** 
    * Get value 
    * 
    * @return string 
    */ 
    public function getValue() 
    { 
     return $this->value; 
    } 
} 

另外我有实体AdMenuLink:用于AdMenuLink

<?php 

namespace AdBackendBundle\Entity; 

use Doctrine\Common\Collections\ArrayCollection; 
use Doctrine\ORM\Mapping as ORM; 

use Symfony\Component\Validator\Constraints as Assert; 

/** 
* AdLink 
* 
* @ORM\Table(name="ad_menu_link") 
* @ORM\Entity(repositoryClass="AdBackendBundle\Repository\AdMenuLinkRepository") 
* @ORM\HasLifecycleCallbacks() 
*/ 
class AdMenuLink 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="AdBackendBundle\Entity\AdMenu", inversedBy="links", fetch="EAGER") 
    * @ORM\JoinColumn(name="menu_id", referencedColumnName="id", onDelete="CASCADE") 
    * @Assert\NotBlank(message="ad_menu_link.field.menu.blank") 
    */ 
    private $menu; 

    /** 
    * @ORM\OneToMany(targetEntity="AdBackendBundle\Entity\AdMenuLink", mappedBy="parent") 
    */ 
    private $children = null; 

    /** 
    * @ORM\ManyToOne(targetEntity="AdBackendBundle\Entity\AdMenuLink", inversedBy="children") 
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE") 
    */ 
    private $parent = null; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="title", type="string", length=255) 
    * @Assert\NotBlank(message="ad_menu_link.field.title.blank") 
    */ 
    private $title; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="description", type="string", length=255, nullable=true) 
    */ 
    private $description; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="url", type="text", nullable=true) 
    */ 
    private $url; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="route", type="string", length=255, nullable=true) 
    */ 
    private $route; 

    /** 
    * @ORM\OneToMany(targetEntity="AdBackendBundle\Entity\AdMenuRouteData", mappedBy="link", cascade={"persist"}) 
    * @Assert\Collection(
    *  fields={ 
    *   "parameter" = @Assert\NotBlank(), 
    *   "value" = @Assert\NotBlank() 
    *  } 
    *) 
    */ 
    private $routeData; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="breadcrumb", type="string", nullable=true) 
    */ 
    private $breadcrumb; 

    /** 
    * @var bool 
    * 
    * @ORM\Column(name="visible", type="boolean") 
    */ 
    private $visible = true; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="weight", type="integer") 
    */ 
    private $weight = 0; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="level", type="integer") 
    */ 
    private $level = 0; 

    public function __construct() 
    { 
     $this->routeData = new ArrayCollection(); 
    } 

    /** 
    * Get id 
    * 
    * @return int 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * Set menu 
    * 
    * @param string $menu 
    * 
    * @return AdMenuLink 
    */ 
    public function setMenu($menu) 
    { 
     $this->menu = $menu; 

     return $this; 
    } 

    /** 
    * Get menu 
    * 
    * @return string 
    */ 
    public function getMenu() 
    { 
     return $this->menu; 
    } 

    /** 
    * Set parent 
    * 
    * @param string $parent 
    * 
    * @return AdMenuLink 
    */ 
    public function setParent($parent) 
    { 
     $this->parent = $parent; 

     return $this; 
    } 

    /** 
    * Get parent 
    * 
    * @return string 
    */ 
    public function getParent() 
    { 
     return $this->parent; 
    } 

    /** 
    * Set children 
    * 
    * @param string $children 
    * 
    * @return AdMenuLink 
    */ 
    public function setChildren($children) 
    { 
     $this->children = $children; 

     return $this; 
    } 

    /** 
    * Get children 
    * 
    * @return string 
    */ 
    public function getChildren() 
    { 
     return $this->children; 
    } 

    /** 
    * Set title 
    * 
    * @param string $title 
    * 
    * @return AdMenuLink 
    */ 
    public function setTitle($title) 
    { 
     $this->title = $title; 

     return $this; 
    } 

    /** 
    * Get title 
    * 
    * @return string 
    */ 
    public function getTitle() 
    { 
     return $this->title; 
    } 

    /** 
    * Set description 
    * 
    * @param string $description 
    * 
    * @return AdMenuLink 
    */ 
    public function setDescription($description) 
    { 
     $this->description = $description; 

     return $this; 
    } 

    /** 
    * Get description 
    * 
    * @return string 
    */ 
    public function getDescription() 
    { 
     return $this->description; 
    } 

    /** 
    * Set url 
    * 
    * @param string $url 
    * 
    * @return AdMenuLink 
    */ 
    public function setUrl($url) 
    { 
     $this->url = $url; 

     return $this; 
    } 

    /** 
    * Get url 
    * 
    * @return string 
    */ 
    public function getUrl() 
    { 
     return $this->url; 
    } 

    /** 
    * Set route 
    * 
    * @param string $route 
    * 
    * @return AdMenuLink 
    */ 
    public function setRoute($route) 
    { 
     $this->route = $route; 

     return $this; 
    } 

    /** 
    * Get route 
    * 
    * @return string 
    */ 
    public function getRoute() 
    { 
     return $this->route; 
    } 

    /** 
    * @return mixed 
    */ 
    public function getRouteData() 
    { 
     return $this->routeData; 
    } 

    /** 
    * @param mixed $routeData 
    */ 
    public function setRouteData($routeData) 
    { 
     $this->routeData = $routeData; 
    } 

    public function addRouteData(AdMenuRouteData $data) 
    { 
     $this->routeData->add($data); 
     $data->setLink($this); 

     return $this; 
    } 

    public function removeRouteData(AdMenuRouteData $data) 
    { 
     $this->routeData->removeElement($data); 
    } 

    /** 
    * @return string 
    */ 
    public function getBreadcrumb() 
    { 
     return $this->breadcrumb; 
    } 

    /** 
    * @param string $breadcrumb 
    */ 
    public function setBreadcrumb($breadcrumb) 
    { 
     $this->breadcrumb = $breadcrumb; 
    } 

    /** 
    * Set visible 
    * 
    * @param boolean $visible 
    * 
    * @return AdMenuLink 
    */ 
    public function setVisible($visible) 
    { 
     $this->visible = $visible; 

     return $this; 
    } 

    /** 
    * Get visible 
    * 
    * @return bool 
    */ 
    public function getVisible() 
    { 
     return $this->visible; 
    } 

    /** 
    * Set weight 
    * 
    * @param integer $weight 
    * 
    * @return AdMenuLink 
    */ 
    public function setWeight($weight) 
    { 
     $this->weight = $weight; 

     return $this; 
    } 

    /** 
    * Get weight 
    * 
    * @return int 
    */ 
    public function getWeight() 
    { 
     return $this->weight; 
    } 

    /** 
    * @return int 
    */ 
    public function getLevel() 
    { 
     return $this->level; 
    } 

    /** 
    * @param int $level 
    */ 
    public function setLevel($level) 
    { 
     $this->level = $level; 
    } 

    /** 
    * @ORM\PrePersist() 
    */ 
    public function prePersist() 
    { 
     if (null !== $this->getParent()) { 
      $this->setLevel($this->getParent()->getLevel() + 1); 
     } 
    } 
} 

我使用形式类型:

<?php 

namespace AdBackendBundle\Form\Type; 

use AdBackendBundle\Entity\AdMenuLink; 
use AdBackendBundle\Form\Type\AdMenuRouteDataType; 
use Symfony\Bridge\Doctrine\Form\Type\EntityType; 
use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; 
use Symfony\Component\Form\Extension\Core\Type\CollectionType; 
use Symfony\Component\Form\Extension\Core\Type\NumberType; 
use Symfony\Component\Form\Extension\Core\Type\TextareaType; 
use Symfony\Component\Form\Extension\Core\Type\TextType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolver; 

class AdMenuLinkType extends AbstractType 
{ 
    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('title', TextType::class, array(
       'label' => 'ad_menu_link.label.title', 
       'translation_domain' => 'forms', 
       'required' => true 
      )) 
      ->add('menu', EntityType::class, array(
       'label' => 'ad_menu_link.label.menu', 
       'class' => 'AdBackendBundle:AdMenu', 
       'choice_label' => 'title', 
       'translation_domain' => 'forms' 
      )) 
      ->add('parent', EntityType::class, array(
       'label' => 'ad_menu_link.label.parent', 
       'class' => 'AdBackendBundle:AdMenuLink', 
       'choice_label' => function(AdMenuLink $adMenuLink) { 
        $separator = ''; 

        for ($i = 0; $i < $adMenuLink->getLevel(); $i++) { 
         $separator .= '- '; 
        } 

        return $separator . $adMenuLink->getTitle(); 
       }, 
       'empty_value' => '-', 
       'translation_domain' => 'forms' 
      )) 
      ->add('url', TextType::class, array(
       'label' => 'ad_menu_link.label.url', 
       'translation_domain' => 'forms' 
      )) 
      ->add('route', TextType::class, array(
       'label' => 'ad_menu_link.label.route', 
       'translation_domain' => 'forms' 
      )) 
      ->add('routeData', CollectionType::class, array(
       'entry_type' => AdMenuRouteDataType::class, 
       'allow_add' => true, 
       'allow_delete' => true, 
       'by_reference' => true 
      )) 
      ->add('breadcrumb', TextType::class, array(
       'label' => 'ad_menu_link.label.breadcrumb', 
       'translation_domain' => 'forms' 
      )) 
      ->add('weight', NumberType::class, array(
       'label' => 'ad_menu_link.label.weight', 
       'empty_data' => 0, 
       'translation_domain' => 'forms' 
      )) 
      ->add('visible', CheckboxType::class, array(
       'label' => 'ad_menu_link.label.visible', 
       'translation_domain' => 'forms' 
      )) 
      ->add('description', TextareaType::class, array(
       'label' => 'ad_menu_link.label.description', 
       'translation_domain' => 'forms' 
      )) 
     ; 
    } 

    /** 
    * @param OptionsResolver $resolver 
    */ 
    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'AdBackendBundle\Entity\AdMenuLink' 
     )); 
    } 
} 
+0

如果您在JavaScript中验证它并在发送表单之前删除空字段,该怎么办? – Pipe

+0

不,我想通过Symfony2约束条件验证 – trauma

+0

请将此代码缩减为必要的最小数量。 – Teepeemm

回答

0

我使用断言有效(),用于这个任务和那个工作。

/** 
    * @ORM\OneToMany(targetEntity="AdBackendBundle\Entity\AdMenuRouteData", mappedBy="link", cascade={"persist"}) 
    * @Assert\Valid() 
    */ 
    private $routeData;