在表单事件symfony中动态禁用表单

Dynamically disable form in form events symfony

我有很多实体,每个实体都有自己的表单类型。一些实体实现 FooBarInterface 包括方法 FooBarInterface::isEnabled();

我想创建一个表单扩展,在所有表单中检查 data_class,如果实体实现 FooBarInterfaceentity::isEnabled() return false,则禁用表单。

<?php
namespace AppBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;

class MyExtension extends AbstractTypeExtension
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $dataClass = $builder->getDataClass();
        if ($dataClass) {
            $reflection = new \ReflectionClass($dataClass);

            if ($reflection->implementsInterface(FooBarInterface::class)) {
                $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $formEvent) {
                    $data = $formEvent->getData(); 
                    if ($data && !$data->isEnabled()) {
                        // todo this need disable all form with subforms
                    }
                });
            }
        }
    }

    public function getExtendedType()
    {
        return 'form';
    }
}

我必须通过 $ builder-> addEventListener,因为 $ builder-> getData () 并不总是有时间创建表格。但是创建表格后,我无法更改她的选项 disabled

如何更改表单中禁用的选项?

我使用方法

创建了表单扩展
    public function finishView(FormView $view, FormInterface $form, array $options) 
    {
        $dataClass = $form->getConfig()->getDataClass();
        if ($dataClass) {
            $reflection = new \ReflectionClass($dataClass);

            if ($reflection->implementsInterface(FooBarInterface::class)) {
                /** @var FooBarInterface$data */
                $data = $form->getData();

                if ($data && !$data ->isEnabled()) {
                   $this->recursiveDisableForm($view);
                }
            }
        }
    }

    private function recursiveDisableForm(FormView $view) 
    {
        $view->vars['disabled'] = true;
        foreach ($view->children as $childView) {
            $this->recursiveDisableForm($childView);
        }
    }

为了在提交数据时禁用更改,我使用 FormEvents::PRE_UPDATE 事件创建了 Doctrine 事件订阅者:

    /**
     * @param PreUpdateEventArgs $args
     */
    public function preUpdate(PreUpdateEventArgs $args)
    {
        $entity = $args->getEntity();

        if (!$entity instanceof DataStateInterface) {
            return;
        }

        if (!$entity->isEnabled()) {
            $args->getEntityManager()->getUnitOfWork()->clearEntityChangeSet(spl_object_hash($entity));
        }
    }