Forms Symfony2:优化表单集合

Forms Symfony2:优化表单集合,forms,performance,symfony,collections,Forms,Performance,Symfony,Collections,在Symfony2应用程序的控制器中,我使用元素集合。元素越多,花费的时间就越多。这听起来合乎逻辑,但似乎有反复的叛逆: 我从MyCollectionType创建了一个表单 在buildForm方法中,我添加了具有自己的buildForm方法的ElementType 然后,当Symfony2使用我传递的元素列表构建表单时,将为每个元素调用ElementType的buildForm方法一次 =>是否不可能先生成第一个ELementType,然后克隆其他ELementType 我不明白为什么这些

在Symfony2应用程序的控制器中,我使用元素集合。元素越多,花费的时间就越多。这听起来合乎逻辑,但似乎有反复的叛逆:

  • 我从MyCollectionType创建了一个表单
  • 在buildForm方法中,我添加了具有自己的buildForm方法的ElementType
然后,当Symfony2使用我传递的元素列表构建表单时,将为每个元素调用ElementType的buildForm方法一次

=>是否不可能先生成第一个ELementType,然后克隆其他ELementType

我不明白为什么这些子表单之间会有任何不同,唯一的不同是设置数据而不是构建表单

然后我注意到buildView方法也是如此:每个元素都有大量重复处理,其中只有数据(可能是侦听器的处理)可能会有所不同。 例如,在我的应用程序中,ElementType有6个字段,集合有700个元素,渲染表单需要30秒。
这是因为表单的处理方式,还是可以优化表单?

答案很简单:你应该优化你的编程技能,而不是symfony表单。这是你关于同一问题的下一个问题


您希望在每个输入周围使用字段集和/或div渲染4200多个字段,因此我怀疑30秒是它在浏览器中渲染的时间。

我为我的一个应用程序添加了相同的问题,我所做的是重新实现了一个基本表单类原型,方法名称与Symfony2几乎相同,并以最简单的方式重新实现,如下所示:


在Twig模板中,我只是迭代数据以创建表单字段、重新填充值并显示错误。表单相同,但生成时间为100ms,而不是30秒。。。对于所有其他表格,我一直使用Symfony2表格。

30是从哪里来的?Symfony或browser?最近出现了不少这样的“巨大形式”问题。归根结底,Symfony表单的设计是为了支持合理数量的元素。表单经过高度设计,开销很大。如果你真的坚持让你的用户使用包含700个输入元素的表单,那么你可能需要一种不同的方法。为了回答你的评论,有很棒的JS库可以在很短的时间内(在现代浏览器中)显示巨大的表liek DataTable。@Rolintocour-是的,因为它们只有在被请求时才使用ajax调用显示,或者我错了,你向我展示了一个有几千个输入字段的神奇页面?一个350行的表格,每行大约有5个输入,使用jquery.html()在IE11或Firefox中5秒钟内显示。当我在客户端模式下使用DataTable时(ia),我插入该表,但立即将.DataTable()应用于该表,它将显示为无delay@Rolintocour-当然,你想告诉我用js插入html比纯html更快吗?我认为插入要显示的巨大html很慢;但是插入巨大的HTML并立即隐藏其中的一部分(在渲染完成之前)速度很快,而且可能会被浏览器优化。这样,我测试了插入整个HTML(350行),立即隐藏所有TR,然后只显示50个first=>这很快
class SimpleForm
{
    /**
     * @var ContainerInterface $container Main application DIC
     */
    protected $container;

    /**
     * @var array $options Options of the form
     */
    protected $options = array();

    /**
     * @var array $options Raw datas for the form.
     */
    protected $data = array();

    /**
     * @var array $options Data of the form against user input.
     */
    protected $boundData = array();

    /**
     * @var array $errors List of errors after form valisation
     */
    protected $errors = array();

    /**
     * @var array $options Tells if the datas were bound to the form.
     */
    protected $isBound = false;

    /**
     * @var array $options Tells if the form validation is ok
     */
    protected $isValid = false;

    /**
     * Main constructor.
     *
     * @param ContainerInterface $container The main DIC
     * @param array              $options   Options of the form
     */
    public function __construct(ContainerInterface $container, $options = array())
    {
        $this->container = $container;
        $this->options   = $options;
        $this->buildForm();
    }

    /**
     * Add widgets to the form.
     */
    public function buildForm()
    {
        $this->widgets['keywordType'] = self::$keywordTypes;
    }

    /**
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * @param array $options
     */
    public function setOptions($options)
    {
        $this->options = $options;
    }

    /**
     * @return string
     */
    public function getEnctype()
    {
        return isset($this->options['enctype']) ? $this->options['enctype'] : '';
    }

    /**
     * If the form is bound it return the bound datas, it returns the raws datas otherwise.
     *
     * @return array
     */
    public function getData()
    {
        return $this->isBound ? $this->boundData : $this->data;
    }

    /**
     * @throws \LogicException
     *
     * @return array
     */
    public function getErrors()
    {
        if ($this->isBound == false) {
            throw new \LogicException('The form must be bound before the errors can be retrieved');
        }

        return $this->errors;
    }

    /**
     * @throws \LogicException
     *
     * @return array
     */
    public function hasErrors()
    {
        if ($this->isBound == false) {
            throw new \LogicException('The form must be bound before the errors can be checked');
        }

        return !empty($this->errors);
    }

    /**
     * @throws \LogicException
     *
     * @return array
     */
    public function getBoundData()
    {
        if ($this->isBound == false) {
            throw new \LogicException('The form must be bound before getting the form final datas');
        }

        return $this->boundData;
    }

    /**
     * @param array $data
     *
     * @return SimpleForm
     */
    public function setData($data)
    {
        $this->data = $data;

        return $this;
    }

    /**
     * Bind the submitted values to the form.
     *
     * @param array $values The values to bind
     *
     * @return SimpleForm
     */
    public function bind($values)
    {
        $values = $this->clean($values);
        $this->boundData = Tools::arrayDeepMerge($this->data, $values);
        $this->isBound = true;
        $this->validate();

        return $this;
    }

    /**
     * Clean raw form values before the validation.
     *
     * @param array $values The raw values submitted by the user.
     *
     * @return array
     */
    protected function clean($values)
    {
        // ...

        return $values;
    }

    /**
     * Run the validation against the form.
     *
     * @return boolean
     */
    protected function validate()
    {
        $this->errors = array();

        // ...

        $this->isValid = empty($this->errors);

        return $this->isValid;
    }

    /**
     * Return the validation state of the form.
     *
     * @throws \LogicException
     *
     * @return boolean
     */
    public function isValid()
    {
        if ($this->isBound == false) {
            throw new \LogicException('The form must be bound before getting the validation status');
        }

        return $this->isValid;
    }

    /**
     * Returns the datas that will be necesary for the view.
     *
     * @return array
     */
    public function createView()
    {
        return array(
            'widgets'   => $this->widgets,
            'options'   => $this->options,
            'data'      => $this->boundData, // Don't forget to escape values against XSS
            'enctype'   => $this->getEnctype(),
            'errors'    => $this->errors,
            'name'      => $this->getName(),
        );
    }

    /**
     * @return string The name of the form
     */
    public function getName()
    {
        return 'search';
    }
}