Symfony2 CollectionType验证

时间:2016-02-19 19:09:09

标签: javascript forms symfony twig

仅当表格中存在来自CollectionType的输入时,我才能以AdMenuLinkType形式验证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:

<?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);
        }
    }
}

我使用AdMenuLink的表单类型:

<?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'
        ));
    }
}

1 个答案:

答案 0 :(得分:0)

我使用assert Valid()来执行此任务,并且可以正常工作。

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