当使用 ORM 验证约束时,Symfony 表单验证将无效子表单设置为有效

问题描述 投票:0回答:1

情况

我有一种带有子表单的表单类型,我使用选项卡在前端呈现,因此一次只能显示一个子表单(作为选项卡)。因此,当不同选项卡上发生错误时,我会弹出一个显示错误的对话框。通过递归循环最终请求处理的表单对象。

验证约束写在表单类型中。这会产生一个我可以循环的最终表单对象,当确实发生错误时,子表单将指示为 valid=false

目标

我想将所有验证约束外包到实体的 ORM 映射中。

问题

当我将所有验证错误外包到 ORM 映射中时,最终的表单对象包含所有 valid=true 的子表单,甚至其内部表单小部件在提交时都带有验证错误。只有最上面的表单级别有效=false。

在构建所有不带事件订阅者的子表单以及带事件订阅者的子表单时,都会发生这种现象。

我希望子表单在最终表单对象上也被设置为无效,当出现错误时,我该如何实现这一点?

  • Symfony 2.8.3
  • 学说 ORM 2.5.4

编辑

使用 error_bubbling 对我来说不起作用。也许我没有正确使用它?

使用此输入:

form
{{ dump(form) }}

form.vars.valid
{{ dump(form.vars.valid) }}

form.vars.errors
{{ dump(form.vars.errors) }}

form.children.sections.vars.errors
{{ dump(form.children.sections.vars.errors) }}

form.children.sections.vars.valid
{{ dump(form.children.sections.vars.valid) }}

form.children.sections.children.general.vars.errors
{{ dump(form.children.sections.children.general.vars.errors) }}

form.children.sections.children.general.vars.valid
{{ dump(form.children.sections.children.general.vars.valid) }}

form.children.sections.children.general.children.lang.vars.valid
{{ dump(form.children.sections.children.general.children.lang.vars.valid) }}

form.children.sections.children.general.children.lang.vars.errors
{{ dump(form.children.sections.children.general.children.lang.vars.errors) }}

我收到此输出:

form
FormView {#12833 ▼
  +vars: array:28 [▶]
  +parent: null
  +children: array:3 [▶]
  -rendered: false}

form.vars.valid
false

form.vars.errors
FormErrorIterator {#12832 ▼
  -form: Form {#5652 ▶}
  -errors: array:1 [▶]
}

form.children.sections.vars.errors
FormErrorIterator {#12837 ▼
  -form: Form {#5649 ▶}
  -errors: []
}

form.children.sections.vars.valid
true

form.children.sections.children.general.vars.errors
FormErrorIterator {#12841 ▼
  -form: Form {#5498 ▶}
  -errors: []
}

form.children.sections.children.general.vars.valid
true

form.children.sections.children.general.children.lang.vars.valid
true

form.children.sections.children.general.children.lang.vars.errors
FormErrorIterator {#12851 ▼
  -form: Form {#2009 ▶}
  -errors: []
}

我在 form.children.sections.children.general.children.lang 中生成的错误。我希望从这个位置来看,递归父母有 ...valid=false

我在以下情况下尝试了error_bubbling=true,具有相同的转储结果。

  • 带有 lang 小部件本身的所有表单类型
  • 没有 lang 小部件本身的所有表单类型
  • lang小部件

我做错了什么,或者我需要其他解决方法?

编辑2

所以现在我在以下情况下尝试了error_bubbling = false,并且仍然相同的转储结果。

  • 带有 lang 小部件本身的所有表单类型
  • 没有 lang 小部件本身的所有表单类型
  • lang小部件

这里有一些片段

实体

/**
 * @ORM\Entity(repositoryClass="Myvendor\CoreBundle\Entity\MyItemRepository")
 * @ORM\Table(name="myitem")
 */
class MyItem
{
   /**
    * @ORM\Column(type="integer")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    protected $id;

    /**
     * @var \Myvendor\CoreBundle\Entity\Language
     *
     * @Assert\Type("Myvendor\CoreBundle\Entity\Languag")
     * @ORM\ManyToOne(targetEntity="Myvendor\CoreBundle\Entity\Language")
     * @ORM\JoinColumn(name="language_id", nullable=true, referencedColumnName="langid")
     */
    private $lang;

/**
 * Set lang
 *
 * @param \Myvendor\CoreBundle\Entity\Language $lang
 *
 * @return MyItem
 */
public function setLang(\Myvendor\CoreBundle\Entity\Language $lang = null)
{
    $this->lang = $lang;

    return $this;
}

/**
 * Get lang
 *
 * @return \Myvendor\CoreBundle\Entity\Language
 */
public function getLang()
{
    return $this->lang;
}
/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}



}

初始表单类型

class MyItemType extends AbstractMyvendorType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $sections = $builder->create('sections', 'form', array(
            'mapped' => false,
            'label' => false,
            'attr' => array(
                'data-sections' => '1'
            ),
            'error_bubbling' => false
          ));
        $builder->add($sections);
        $builder->addEventSubscriber(new DynamicSubforms());
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        parent::configureOptions($resolver);
        $resolver->setDefaults(array(
            'error_bubbling' => false
        ));
    }
}

事件订阅者

class DynamicSubforms implements EventSubscriberInterface
{

    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_SET_DATA => 'onPreSetData'
        );
    }

    /**
     * Adding subtypes, depending on the myitem type.
     *
     * @author FPI
     * @param FormEvent $event            
     */
    public function onPreSetData(FormEvent $event)
    {
        /**
         *
         * @var $data \Myvendor\CoreBundle\Entity\MyItem
         * @var $form \Symfony\Component\Form\Form
         */
        $data = $event->getData();
        $steptype = $data->getType();
        $form = $event->getForm();
        $options = $form->getConfig()->getOptions();
        $sections = $form->get('sections');

        $default_section_options = array(
            'mapped' => false,
            'data' => $data
        );
        // Every steptype has section "general"
        $sections->add('general', GeneralType::class, array_merge($default_section_options, array(
            'label' => 'general',
            'error_bubbling' => false
        )));

    }
}

子表单类型

class GeneralType extends AbstractType
{

    protected $em;

    protected $choiceOption;

    public function __construct(EntityManager $em, ChoiceOption $choice_option)
    {
        $this->em = $em;
        $this->choiceOption = $choice_option;
    }

    /*
     * Here are set the static options for each widget.
     * The dynamic options on specific widgets are specified in the event subscriber.
     * {@inheritdoc}
     *
     * @author FPI
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        /* Language */
        $builder->add('lang', 'entity', array(
            'label' => 'language',
            'class' => 'MyvendorCoreBundle:Language',
               'error_bubbling' => false
        ));

    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'error_bubbling' => false
        ));
    }
}
php symfony validation orm doctrine
1个回答
0
投票

如果您不希望将错误传递给表单父级,则应将

error_bubbling
设置为 false,因为默认情况下
error_bubbling
为 false 除非表单是复合表单 (error_bubbling)。

© www.soinside.com 2019 - 2024. All rights reserved.